Calculate number of decimal digits in BigInteger - java

I'm trying to use BigInteger values along side Math.Log10 method.
final BigInteger answerNo = fact;
final int digits = 1 + (int)Math.floor(Math.log10(answerNo));
Unfortunately the compiler says incompatible types.
If I change the ints to BigIntegers it still doesn't like it.

Instead of doing a log10 you can find the number of digits by simply doing:
int digits = answerNo.toString().length();

You can't assign an int to a BigInteger - you could write: final BigInteger answerNo = BigInteger.valueOf(fact);
Mat.log10 expects a double, not a BigInteger
If you don't mind a loss of precision, you could simply use doubles:
final int digits = 1 + (int)Math.floor(Math.log10(fact));
If you care about precision, you will need to calculate the log manually.

BigInteger.toString() can be inefficient in terms of memory if you only care for count of digits.
You can instead try converting BigInteger into a BigDecimal and use the BigDecimal.precision() to achieve the same. See this answer for details.

Related

NumberFormatException when constructing BigInteger from result of Math.pow

I'm trying to work with some larger integer values but I'm having some issues initializing my BigInteger variable. I've been doing:
BigInteger x = new BigInteger("" + (Math.pow(2, n)));
Where n is some number in the 100s, but this is throwing a NumberFormatException. I don't think I can use BigInteger,Valueof() because that takes a long which i don't believe is big enough. Any help would be appreciated.
One way or another Math.pow returns a value of type double which will be formatted with a decimal separator. BigInteger cannot accept decimal values.
Throws:
NumberFormatException - val is not a valid representation of a BigInteger.
Just use the pow method provided by BigInteger
BigInteger x = BigInteger.TWO.pow(n);

Why am I losing Bigdecimal precision?

I am converting numbers like 5.326.236,56 (money), from a txt and first removing dots and commas, but im losing the decimals, and I already defined the columns as:
#Column(name = "total", precision = 16, scale = 2)
private BigDecimal total;
but I am losing the last 2 digits that correspond to Decimal part
Here is my code:
private BigDecimal parseBigLong(String stringNumber) {
String cvalue = "";
for (int n = 0; n < stringNumber.length(); n++) {
char c = stringNumber.charAt(n);
if (!(".").equals(String.valueOf(c))) {
if (!(",").equals(String.valueOf(c))) {
if (!("-").equals(String.valueOf(c))) {
cvalue = cvalue + c;
}
}
}
}
BigDecimal bigDecimal = ( BigDecimal.valueOf(Long.parseLong(cvalue) / 100));
return bigDecimal;
}
Basically, you are doing an integer division on the long before constructing the BigDecimal.
Naturally, the integer division is producing another long ... which cannot represent those two digits after the decimal point.
You can avoid this by doing the division using BigDecimal:
BigDecimal bigDecimal = BigDecimal.valueOf(Long.parseLong(cvalue))
.divide(new BigDecimal(100));
Or if you don't need to enforce the constraint that cvalue is a valid integer (long) representation:
BigDecimal bigDecimal = (new BigDecimal(cvalue))
.divide(new BigDecimal(100));
There may be a better way. The DecimalFormat class understands all sorts of (localized) number formats. If you create a suitable format and then call setParseBigDecimal(true) the format's parse method will produce a BigDecimal ... directly ... without any string bashing to get rid of comma and period characters. (And you won't need to assume that the input number has exactly two digits after the decimal.)
First, your conversion logic is strange:
You are ripping off all -, , and . from your String, and assume it to be 2 decimals when constructing the BigDecimal.
Which means, if you are given a string 1234.5678, you are going to build 123456.78 as the result.
Depending on what's your intention, here are the answers:
If you want to convert to BigDecimal based on the value in input string
Which means, if you want String "1,234.5678" to become 1234.5678 in BigDecimal, you could make use of DecimalFormat, as described in this question: https://stackoverflow.com/a/18231943/395202
If the strange logic is what you intended to do
Which means, if you want String "1,234.5678" to become 123456.78 in BigDecimal, the specific problem in your code is you are doing a long division, and use the result to construct BigDecimal.
In Java (and many other language), division of integer with integer is going to give you integer as result, so 123456 / 100 is going to give you 1234.
What you want to achieve could be done by
BigDecimal result = BigDecimal.valueOf(longValue).divide(BigDecimal.valueOf(100));
Going back to your code, there are a lot of other problems:
Your string concatenation logic is highly inefficient. You could use StringBuilder (or other way I am suggesting soon)
You do not need to convert a char to a String to do comparison. So you
if (!(".").equals(String.valueOf(c))) {
should be written
if (c != '.') {
You could simply use regex to cleanse your input string:
String cvalue = stringNumber.replaceAll("[.,-]", "");

Java : Need to get the same functionality of the Integer.toHexString() with a String parameter and not an Int parameter due to NumberFormat Exception

I have this line of Java code that will throw NumberFormatException if the number represented as a String is above 2,147,483,647.
Because:
The int data type is a 32-bit signed two's complement integer. It has
a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647
Code Throwing the NumberFormatException:
String largeNumberAsAString = "9999999999";
Integer.toHexString(Integer.parseInt(largeNumberAsAString)); // NumberFormatException
How can I get the same functionality of theInteger.toHexString() with a String parameter and not an int parameter due to NumberFormatException?
Use BigInteger to avoid numeric limits of primitive int and long:
BigInteger x = new BigInteger("9999999999999999999999"); // Default radix is 10
String x16 = x.toString(16); // Radix 16 indicates hex
System.out.println(x16);
The class conveniently exposes a constructor that takes a String, which gets interpreted as a decimal representation of a number.
Demo.
If your input value can be arbitrarily large, then #dasblinkenlight's answer involving BigInteger is your best bet.
However, if your value is less than 263, then you can just use Long instead of Integer:
String dec = "9999999999";
String hex = Long.toHexString(Long.parseLong(dec));
System.out.println(hex); // 2540be3ff
Live demo.
Use Integer.parseUnsignedInt
When the number is above 2^31 but below 2^32, thus in the negative int range,
you can do:
int n = Integer.parseUnsignedInt("CAFEBABE", 16);
(I used hexadecimal here, as it is easier to see that above we are just in that range.)
However 9_999_999_999 is above the unsigned int range too.
Try this way:
String largeNumberAsAString = "9999999999";
System.out.println(Integer.toHexString(BigDecimal.valueOf(Double.valueOf(largeNumberAsAString)).intValue()));

Datatype to store 20 digit number

I have a number of 20 digit, which datatype will support to store this number? I have tried long, double but I 'm getting out of range.
Number = 48565664968483514466
Then I have to convert this number to Base36 to generate the barcode.
BigInteger:
The BigInteger class allocates as much memory as it needs to hold all the bits of data it is asked to hold and also provides operations analogues to all of Java's primitive integer operators and for all relevant methods from java.lang.Math.
Declare it as
BigInteger bi1 = new BigInteger("12345678900123");
To convert your number in base 36:
BigInteger number = new BigInteger("48565664968483514466");
String numberInBase36 = number.toString(36);
System.out.println(numberInBase36);
when I'm trying to use new BigInteger(number), I'm getting literal of type int is out of range
The syntax you are looking for is
BigInteger n = new BigInteger("48565664968483514466");
with the numeric literal as a String, since the primitive integer literals cannot hold a number this large.
BigInteger i = new BigInteger("48565664968483514466");

How do you convert a binary string like "10010010101" to a BigInteger decimal representation?

I know that integers have Integer.parseInt(string, 2); but when the value of the decimal is very large, how can we use BigInteger in this case?
BigInteger(giantBinaryString, 2);
There's a constructor for that.
Use the constructor BigInteger(String s)
documentation: http://docs.oracle.com/javase/6/docs/api/java/math/BigInteger.html
For a binary integer represented as a string, use
BigInteger(binaryString, 2);
In this case you can construct a BigInteger from a string which
denotes a very very large integer. This is the purpose of BigInteger.
If you don't use BigInteger it will overflow your int variable.
You can do this by calling.
BigInteger b = new BigInteger(str, radix);
where you pass in radix = 2 or radix = 10 or whatever
you need (seems you need 2 in your case) and str is the value.
Then you can use
b.toString(radix);
to output your BigInteger value in whatever radix you want.
I think you are looking for this BigInteger(binaryString, 2);

Categories