Value out of range for int in Clojure - java

Normally whilst programming in LibGDX, passing the Color class an integer of a hex value works just fine:
new Color(0xeaeaeaff);
But doing this from Clojure...
(Color. 0xeaeaeaff)
... generates the error java.lang.IllegalArgumentException: Value out of range for int: 3,941,264,128. Sure that value does look out of range, very much so. But when I normally do it from Java, there is no problem at all?
The Clojure value is defined like so:
(def color 0xff00ffff)
Why does this happen?

The easiest way to get the same value that Java would give you, with the same literal as the input, is to use unchecked-int. It will return a negative (overflowed) number, just like the original, rather than giving an out of bounds error.
+user=> (unchecked-int 0xeaeaeaff)
-353703169

0xeaeaeaff in Java represents a negative number: -353703169 and causes overflow in Clojure (Java is just overflowing it to a negative number).
In your case 0xeaeaeaff in Java is equal to -353703169 in base 10. You can write it just as -353703169 in Clojure, or in base 16 as -16r15151501.
You can use unchecked-int as pointed out by noisesmith.

In Java, using literal notation for hexadecimal numbers produces ints, so 0xeaeaeaff is an int with the value -353703169, because it exceeds the max value for ints, overflows and becomes a negative int.
In Clojure 0xeaeaeaff produces a long with the value 3941264127.
The class com.badlogic.gdx.graphics.Color of LibGDX has a constructor that expects an int but not one that expects a long, which you are passing to it in the Clojure case, hence the exception: java.lang.IllegalArgumentException: Value out of range for int: 3,941,264,128.
You could just pass -353703169 to the constructor or use (Integer/parseUnsignedInt "eaeaeaff" 16) like Piotrek suggested, as it would probably be more convinient, possibly through a wrapper function:
(defn hex->int [arg]
(Integer/parseUnsignedInt arg 16))

Related

Prevent java from producing incorrect result

System.out.println((int) (368*Math.pow(2416,2)+100*2416+100));
does not produce the same output as a calculator would or python, what might be the reason for this?
The result of the expression is larger than the range of java int.
Since you are casting to int (java primitive type) which ranges from -2,147,483,648 (-2^31) to 2,147,483,647 ((2^31)-1), the code produces 2147483647(upper limit of java int data-type) as the output whereas the calculator will give correct result.

Number too big for BigInteger

I'm developing a chemistry app, and I need to include the Avogadro's number:
(602200000000000000000000)
I don't really know if I can use scientific notation to represent it as 6.022 x 10x23 (can't put the exponent).
I first used double, then long and now, I used java.math.BigInteger.
But it still says it's too big, what can I do or should this is just to much for a system?
Pass it to the BigInteger constructor as a String, and it works just fine.
BigInteger a = new BigInteger("602200000000000000000000");
a = a.multiply(new BigInteger("2"));
System.out.println(a);
Output: 1204400000000000000000000
First of all, you need to check your physics / chemistry text book.
Avogadro's number is not 602,200,000,000,000,000,000,000. It is approximately 6.022 x 1023. The key word is "approximately". As of 2019, the precise value is 6.02214076×1023 mol−1
(In 2015 when I originally wrote this reply, the current best approximation for Avogadro's number was 6.022140857(74)×1023 mol−1, and the relative error was +/- 1.2×10–8. In 2019, the SI redefined the mole / Avogadro's number to be the precise value above. Source: Wikipedia)
My original (2015) answer was that since the number only needed 8 decimal digits precision, the Java double type was an appropriate type to represent it. Hence, I recommended:
final double AVOGADROS_CONSTANT = 6.02214076E23;
Clearly, neither int or long can represent this number. A float could, but not with enough precision (assuming we use the best available measured value).
Now (post 2019) the BigInteger is the simplest correct representation.
Now to your apparent problems with declaring the constant as (variously) an double, a long and a BigInteger.
I expect you did something like this:
double a = 602200000000000000000000;
and so on. That isn't going to work, but the reason it won't work needs to be explained. The problem is that the number is being supplied as an int literal. An int cannot be that big. The largest possible int value is 231 - 1 ... which is a little bit bigger than 2 x 109.
That is what the Java compiler was complaining about. The literal is too big to be an int.
It is too big for long literal as well. (Do the math.)
But it is not too big for a double literal ... provided that you write it correctly.
The solution using BigInteger(String) works because it side-steps the problem of representing the number as a numeric literal by using a string instead, and parsing it at runtime. That's OK from the perspective of the language, but (IMO) wrong because the extra precision is an illusion.
You can use E notation to write the scientific notation:
double a = 6.022e23;
The problem is with how you're trying to create it (most likely), not because it can't fit.
If you have just a number literal in your code (even if you try to assign it to a double or long), this is first treated as an integer (before being converted to the type it needs to be), and the number you have can't fit into an integer.
// Even though this number can fit into a long, it won't compile, because it's first treated
// as an integer.
long l = 123456788901234;
To create a long, you can add L to your number, so 602200000000000000000000L, although it won't fit into a long either - the max value is 263-1.
To create a double, you can add .0 to your number, so 602200000000000000000000.0 (or 6.022e23 as Guffa suggested), although you should not use this if you want precise values, as you may lose some accuracy because of the way it stores the value.
To create a BigInteger, you can use the constructor taking a string parameter:
new BigInteger("602200000000000000000000");
Most probably you are using long to initialize BigInteger. Since long can represent 64-bit numbers, your number would be too big to fit in to long. Using String would help.

BigDecimal.intValue() returns Unexpected Number

I'm running into a strange java bug using the intValue() from the BigDecimal class.
I'm starting with a value of 3300028000.
When I call the following code:
int i = d.intValue();
it returns: -994939296
Any ides as to why this would happen?
An int can't hold a value that big, so it overflows. Try using a long.
When you try to fit this number into an int variable, it overflows, since the int type in Java has 32 bits, ergo an int variable can store values that range from −2,147,483,648 to 2,147,483,647.
To store the value of your BigInteger, you have to use a long variable. Try this:
long value = d.longValue();
What would you like it to return? :)
As described in the javadocs:
if the resulting "BigInteger" is too big to fit in an int, only the
low-order 32 bits are returned
intValueExact, on the other hand, would throw an exception.
You should really read Java API before blaming it:
Converts this BigDecimal to an int. This conversion is analogous to
the narrowing primitive conversion from double to short as defined in
section 5.1.3 of The Java™ Language Specification: any fractional part
of this BigDecimal will be discarded, and if the resulting
"BigInteger" is too big to fit in an int, only the low-order 32 bits
are returned. Note that this conversion can lose information about the
overall magnitude and precision of this BigDecimal value as well as
return a result with the opposite sign.
I don't know why you need the int value of a BigDecimal but the class BigDecimal contains lots of methods to fit your request.
compareTo
add
substract
multiply
divide
etc..
I would work with BigDecimal itself. Sooner or later; Converting the BigDecimal type to other primitive types will end up with an error. Cuz all of them has a limit.

C stroull equivalent in Java

I have a Objective C code,which I have to translate in Java,but I have a little problem with converting one line. In Objective C code I have : UInt64 iz = strtoull(s,&s1,16);. I was searching over the internet abotu strtoull and I find this information for it :
strtoul will convert a string to an unsigned long integer. An
important feature of this function is the ability to accept data in
various number bases and convert to decimal.
The first argument must not contain a + or -. The second argument
(char **endptr) seems to be a waste of space! If it is set to NULL,
STRTOL seems to work its way down the string until it finds an invalid
character and then stops. All valid chars read are then converted if
the string starts with an invalid character the function returns ZERO
(0).
The Third argument (base) can have a value of 0 or 2-32.
0 - strtol will attempt to pick the base. Only Dec, Oct Hex supported.
2-31 - The base to use.
I tried to find a way to do this in Java.As a made some researches I got this :
long l=Long.parseLong(md5Hash, 16);
And my question is,is parseLong equivalent to strtoull and can I use it for my application? If not can you suggest me what can I use?
Thanks in advance!
You can't because long is signed in Java. If you need unsigned integers for the full value range of 64 Bit then you have to use the BigInteger class.
Long.parseLong is the usual way of parsing a string into a long. But be aware that Java does not have unsigned types.
It is equivalent but keep in mind that long in Java is not unsigned. Therefore, a Java long is in [-2^63, 2^63 - 1].
use
BigInteger(String val, int radix)

Parse number with positive/negative prefix from string in java

It's quite straight forward in java to parse number from String, i.e. with Integer.parseInt(s) if string in the format 'n' or '-n', but unfortunately it fails to parse string in the format of '+n'.
So what is the most effective/elegant way to parse number from string in java if it contains positive or negative prefix: '+n' or '-n' ?
Integer.parseInt(s.replace("+", ""));
In truth there are many gotchas using Integer to parse numbers like that, in that Integer has very specific bounds of size and format ("1,000,000.00") isn't parsing that way, but I'm taking your question as Integer.parseInt meets your needs just fine, you just have to deal with a + in your data.
Just FYI, this has been fixed in Java 7.
from, Java SE8 for the Really Impatient
Prior to JDK 1.7, what was the result of the following code segment?
double x = Double.parseDouble("+1.0");
int n = Integer.parseInt("+1");
Pat yourself on the back if you knew the
answer: +1.0 has always been a valid floating-point number, but
until Java 7, +1 was not a valid integer. This has now been fixed
for all the various methods that construct int, long, short, byte,
and BigInteger values from strings. There are more of them than you
may think. In addition to parse (Int|Long|Short|Byte), there are
decode methods that work with hexadecimal and octal inputs, and
valueOf methods that yield wrapper objects. The BigInteger(String)
constructor is also updated.

Categories

Resources