A datatype long in Java 7 is throwing numberformatexception when it is exceeding 20 digits. Is there any alternative here?
You can use BigIntegers to do mathematical operations with higher number of digits.
But in division, it is doing integer division.(As in integer data types). For large decimal number calculations, you can use BigDecimal
An Example using BigInteger is shown below..
BigInteger b1 = new BigInteger("100000000000000000000000000000000000000000");
BigInteger b2 = new BigInteger("100000");
System.out.println("Addition: " + b1.add(b2));
System.out.println("Subtraction: " + b1.subtract(b2));
System.out.println("Division: " + b1.divide(b2));
System.out.println("Multiplication: " + b1.multiply(b2));
System.out.println("Power: " + b1.pow(1000));
For more information you can just google how to use biginteger in java
Related
byte byteChallenge = 68;
short shortChallenge = 190;
int intChallenge = 2147483647;
long longChallenge = (50000L + 10L * (byteChallenge + shortChallenge + intChallenge));
long longChallengeX = 50000L + 10L * ((long) byteChallenge + (long) shortChallenge + (long)
intChallenge);
System.out.println(longChallenge);
System.out.println(longChallengeX);
The output I'm getting is:
-21474783910
21474889050
The tricky part is int intChallenge = 2147483647 constant which is the maximum value for positive int (see Integer.MAX_VALUE).
When you perform byteChallenge + shortChallenge + intChallenge it is an int arithmetic statement which results in integer overflow. In your example the integer overflow result is a negative number.
When you perform (long) byteChallenge + (long) shortChallenge + (long) intChallenge it is long arithmetic. Since long supports much larger values than int there is no overflow.
In the first scenario, the sub-expression (byteChallenge + shortChallenge + intChallenge) is basically "byte + short + int". Java evaluates this part first, before multiplying by 10 and adding to 50000.
Since the sub-expression doesn't involve a long type, Java has no reason to make the result type of the expression long, so the first two operands is only promoted to int and the three ints are added together to give another int. This causes an overflow, making the result very negative.
In the second case, you explicitly cast all three operands to long before operating on them, so the type of the sub-expression is resolved to be long.
The lesson here is that nested expressions are treated the same as any other expressions. (byteChallenge + shortChallenge + intChallenge) doesn't get special treatment just because it is multiplied with a long. Its value is still evaluated the same way.
I have a StreamTokenizer that accepts numbers. However, the parsed number is not the same as the input.
Sample code:
String str = "1000000000000.0000000000000";
double initial = 1000000000000.0000000000000;
InputStream in = new ByteArrayInputStream(str.getBytes());
StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(in)));
input.parseNumbers();
int n = input.nextToken();
if (n == StreamTokenizer.TT_NUMBER) {
System.out.println("Original: " + str);
System.out.println("Parsed: " + input.nval);
System.out.println(initial + " == " + input.nval + " -> " + (initial == input.nval));
}
Output:
Original: 1000000000000.0000000000000
Parsed: 9.999999999999999E11
1.0E12 == 9.999999999999999E11 -> false
How can this be prevented so the two double values are equal?
EDIT: Linked question discusses why this issue appears. I am asking what are the possible ways to avoid this issue.
An exact way of representing numbers is usage of BigDecimal. Double has a certain precision and working with doubles of various precision (EX: double1=10000.0 and double2=0.0001) could result that the 0.0001 to be dropped. BigDecimal avoids that.
The disadvantages of BigDecimal:
it's slower
operators +, -, *, and / are not overloaded
But if you are dealing with money or having precision is a must, you should use BigDecimal, otherwise you will have losses.
EX:
String str = "1.0E12";
double initial = 1000000000000.0000000000000;
BigDecimal exVal = new BigDecimal(str);
System.out.println("Original: " + str);
System.out.println("Parsed: " + exVal);
System.out.println(initial + " == " + exVal + " -> " + (initial == exVal.doubleValue()));
Program output:
Original: 1.0E12
Parsed: 1.0E+12
1.0E12 == 1.0E+12 -> true
As per David Conrad's analysis, the StreamTokenizer classes handling of numbers with decimal points is flawed, and there doesn't appear to be a work-around.
But this is only one of many short-comings flaws in this class. You would be better off using Scanner or String.split. If the input is really complicated, consider using a parser generator to generate a lexer / parser that precisely implements your input syntax.
Related bugs:
JDK-4638205 : StreamTokenizer: lost precision when parsing long values
JDK-4146533 : java.io.StreamTokenizer: Want to parse scientific numbers
JDK-8180207 : deprecate StringTokenizer and StreamTokenizer
Having said that, applications that use floating point numbers should be tolerant of issues caused by rounding errors and imprecision. There are a number of Q&As on the best way to compare floating point numbers; e.g.
Manipulating and comparing floating points in java
I'm trying in the following code to round a decimal number based on the decimal format that I set at the beginning:
DecimalFormat df = new DecimalFormat("#.000");
df.setRoundingMode(RoundingMode.FLOOR);
double a = Double.parseDouble(df.format(43.473684210526315));
double b = Math.pow(a, 10);
double c = Double.parseDouble(df.format(b));
System.out.println(a + " ** " + b + " ** " + c);
The result that I got is:
43.473 ** 2.4109939006965688E16 ** 2.4109939006965688E16
As you see, the value of a is formatted properly. While the other values are not. After spending a long time trying to understand what is going on, I found out the value 2.4109939006965688E16 can not be formatted. I tested the same value after removing E16 and it worked.
My question is how can I round such a large decimal so that it works as the a?
It's pure luck that a works. If the initial value was 43.4701 you would be seeing 43.47. And in some cases you would see more than 3 decimal places due to the inaccuracy of double.
You only use the DecimalFormatter to create a String briefly before turning back into a double again. You want to keep and use that string.
DecimalFormat df = new DecimalFormat("#.000");
double b = Math.pow(43.473684210526315, 10);
String bFormatted = df.format(b);
System.out.println(bFormatted);
Gives you your desired output 24115485538109308.000
For your "big" decimals you can use the following format:
DecimalFormat df2 = new DecimalFormat("#.000E0");
I see several issues here:
You do not specify a locale for your DecimalFormat. So the combination of DecimalFormat.format and Double.parseDouble is error prone, as e.g. with german locale, DecimalFormat.format will use a comma as decimal separator, which is unsupported by Double.parseDouble, and will throw a NumberFormatException. You should use both format and parse of your DecimalFormat.
Also, you use your double values directly for System.out.println. Why not concatenating the results of DecimalFormat.format, to achieve exactly what you want? E.g. System.out.println(df.format(a) + " ** " + df.format(b) + " ** " + df.format(c));
If you want to do real mathematical rounding (e.g. needing the double value for additional calculations), use Math.round. You can multiply and divide by 10, 100, 1000 etc. to achieve the desired precision. Note that, with the double data type, you can't do exact rounding.
For large numbers, you'll need to use BigInteger or BigDecimal
DecimalFormat df = new DecimalFormat("#.000");
df.setRoundingMode(RoundingMode.FLOOR);
BigDecimal a = new BigDecimal(43.473);
BigDecimal b = a.pow(10);
System.out.println(df.format(a) + " ** " + b.doubleValue() + " ** " + df.format(b));
This results in the following output
43.472 ** 2.4109939006965688E16 ** 24109939006965686.655
When i run this code it gives NumberFormatException? how do i convert A49D43C5 this numbers to decimal in java?
logger.info("Decimal value: " + Integer.parseInt("A49D43C5", 16));
That number is larger than an int (Integer.MAX_VALUE is 231 - 1 or 2147483647). You could use a long like
System.out.println("Decimal value: " + Long.parseLong("A49D43C5", 16));
Output is
Decimal value: 2761769925
Integer's max value is 2147483647.
try to use BigInteger for your hexadecimal.
BigInteger bigInt = new BigInteger(hexString, 16);
I'd like to store a long integer in Java, specifically the 6144-bit MODP Group (Group 17) from RFC 3526. However this number does not seem to fit to a BigInteger. Is there a way to use this prime number in Java?
EDIT: I tried
BigInteger p = new BigInteger(Integer.toString(pValue));
p = 33751521821438561184518523159967412330064897805741846548173890474429429901326672445203235101919165483964194359460994881062089387893762814044257438204432573941083014827006090258925875161018096327732335800595831915976014208822304007327848132734933297885803213675261564962603340457220776826322500058091310967253976619973988033663666385188155212656268079501726223369693427999804134467810120772356498596945532366527400517575471969335854905274504119509592366013711954148258884879224599915203456315881034776553083676995718335598586395591169999570824515035017543533352697525287753332500527176569576894926734950469293596134095086603716860086302051544539652689091299099784588919052383463057789440565460681441902442399956419060521629604697347879024654313800186078316526964529288062740879011035175920059192178561473199006205896719435014765345518490882366607110905303449152556221163232127426440691921134648766635695850239231304591744215610985029636895406718880766308249227315984267542266259489684372223916445411015900506239419267909716320331208988978180868987431623710347617992356201449023892203230133009421463914291201346063125219636964261683591541014344239275340735690997732222069758773963390876360546515755280517042160525487302898122311669799679447530453600399342697032714458549591285939453949034981248114322322367238645042515984447890788917823576330019151696568654314153058547592091366014550143819685170068343700104677609041166369760080933413605498962382077778845599834907475953430787446201384567328530675275792962354883770806900827183685718353469574731680520621944540947734619035177180057973022652571032196598229259194875709994709721793154158686515748507274224181316948797104601068212015232921691482496346854413698719750190601102705274481050543239815130686073601076304512284549218459846046082253596762433827419060089029417044871218316020923109988915707117567;
Use the BigInteger(String val) constructor to create the number, that is: pass the number as a String. The BigInteger class implements an arbitrary-precision integer data type, any integer can fit - as long as there's enough physical memory to represent it:
BigInteger p = new BigInteger("33751521821438561184518523159967412330064897805741846548173890474429429901326672445203235101919165483964194359460994881062089387893762814044257438204432573941083014827006090258925875161018096327732335800595831915976014208822304007327848132734933297885803213675261564962603340457220776826322500058091310967253976619973988033663666385188155212656268079501726223369693427999804134467810120772356498596945532366527400517575471969335854905274504119509592366013711954148258884879224599915203456315881034776553083676995718335598586395591169999570824515035017543533352697525287753332500527176569576894926734950469293596134095086603716860086302051544539652689091299099784588919052383463057789440565460681441902442399956419060521629604697347879024654313800186078316526964529288062740879011035175920059192178561473199006205896719435014765345518490882366607110905303449152556221163232127426440691921134648766635695850239231304591744215610985029636895406718880766308249227315984267542266259489684372223916445411015900506239419267909716320331208988978180868987431623710347617992356201449023892203230133009421463914291201346063125219636964261683591541014344239275340735690997732222069758773963390876360546515755280517042160525487302898122311669799679447530453600399342697032714458549591285939453949034981248114322322367238645042515984447890788917823576330019151696568654314153058547592091366014550143819685170068343700104677609041166369760080933413605498962382077778845599834907475953430787446201384567328530675275792962354883770806900827183685718353469574731680520621944540947734619035177180057973022652571032196598229259194875709994709721793154158686515748507274224181316948797104601068212015232921691482496346854413698719750190601102705274481050543239815130686073601076304512284549218459846046082253596762433827419060089029417044871218316020923109988915707117567");
That number will easily fit into a Java BigInteger, but both methods you're using to get it are using an intermediate form into which it cannot fit:
BigInteger p = new BigInteger(Integer.toString(pValue));
p = 337515218214385611845185231599674123300648978057418465481...7117567;
The former won't work because the Integer class cannot hold a number that big. The latter won't work because a "naked" number in your source code is treated as an int.
With the actual hex value taken from RFC3526, the following program shows how to do it:
import java.math.BigInteger;
public class Test
{
public static void main(String[] args) {
BigInteger num = new BigInteger(
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" +
"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" +
"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" +
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" +
"49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8" +
"FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C" +
"180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718" +
"3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D" +
"04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D" +
"B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226" +
"1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC" +
"E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26" +
"99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB" +
"04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2" +
"233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127" +
"D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" +
"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406" +
"AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918" +
"DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151" +
"2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03" +
"F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F" +
"BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" +
"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B" +
"B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632" +
"387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E" +
"6DCC4024FFFFFFFFFFFFFFFF", 16);
System.out.println(num);
}
}
The output of that program is:
33751521821438561184518523159...8915707117567