Prevent java from producing incorrect result - java

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.

Related

Why casting a very large long number to int gives us a strange output (Java)?

I was practicing some castings in Java and I faced a situation for which I couldn't find any answers, anywhere. There are a lot of similar questions with answers, but none gave me an explanation for this particular case.
When I do something like
long l = 165787121844687L;
int i = (int) l;
System.out.println("long: " + l);
System.out.println("after casting to int: " + i);
The output is
long: 165787121844687
after casting to int: 1384219087
This result is very intriguing for me.
I know that the type long is a 64-bit integer, and the type int is a 32-bit integer. I also know that when we cast a larger type to a smaller one, we can lose information. And I know that there is a Math.toIntExact() method that is quite useful.
But what's the explanation for this "1384219087" output? There was loss of data, but why this number? How "165787121844687" became "1384219087"? Why does the code even compile?
That's it. Thanks!
165787121844687L in hex notation = 0000 96C8 5281 81CF
1384219087 in hex notation = 5281 81CF
So the cast truncated the top 32 bits as expected.
32-bits
deleted
▼▼▼▼ ▼▼▼▼
165_787_121_844_687L = 0000 96C8 5281 81CF ➣ 1_384_219_087
64-bit long ▲▲▲▲ ▲▲▲▲ 32-bit int
   32-bits
remaining
If you convert these two numbers to hexadecimal, you get
96C8528181CF
528181CF
See what's happened here?
The Answer by OldProgrammer is correct, and should be accepted. Here is some additional info, and a workaround.
Java spec says so
Why does the code even compile?
When you cast a numeric primitive in Java, you take responsibility for the result including the risk of information loss.
Why? Because the Java spec says so. Always best to read the documentation. Programming by intuition is risky business.
See the Java Language Specification, section 5.1.3. Narrowing Primitive Conversion. To quote (emphasis mine):
A narrowing primitive conversion may lose information …
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.
Math#…Exact…
When you want to be alerted to data loss during conversion from a long to a short, use the Math methods for exactitude. If the operation overflows, an execution is thrown. You can trap for that exception.
try
{
int i = Math.toIntExact( 165_787_121_844_687L ) ; // Convert from a `long` to an `int`.
}
catch ( ArithmeticException e )
{
// … handle conversion operation overflowing an `int` …
}
You will find similar Math#…Exact… methods for absolute value, addition, decrementing, incrementing, multiplying, negating, and subtraction.

Value out of range for int in Clojure

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))

Frege Double to Integer

I would like to be able to convert a large Double to an Integer, but it seems that the Frege Haskell implementation of floor does not yield an Integral type. Instead, it seems to be implemented to interface with way Java does it, and takes a Floating type to a Double, Floating r => r -> Double. I could use round, but that rounds rather than truncate (though I might be able to subtract 0.5 and then round). I'd rather work without needing to resort to using Int or Long, which, as wide as the latter is, is still limited in precision.
Any way to go about flooring a floating point type to an arbitrary precision integer type?
This functionality is indeed not available. The reason is that Java apparently doesn't offer methods that support it.
What you can do is to convert the (floored) double to a String and converting that to an Integer.
Here is an example:
frege> import Prelude.Math(floor)
frege> integerFromDouble d = String.aton ("%.0f".format (floor d))
function integerFromDouble :: Math.Floating a => a -> Integer
frege> integerFromDouble 987654321e20
98765432100000000000000000000
I wonder if there is a more effective method that somehow extracts the mantissa and exponent from a Double and computes the Integer.
Note that above function is unsafe because NaN, +Infinity and -Infinity exist:
frege> integerFromDouble (5/0)
java.lang.NumberFormatException: For input string: "Infinity"
You could either check that separately or replace String.aton with String.integer , which returns
Either NumberFormatException Integer
If you can make sure your computations don't exceed the Long capacity, what you want can be done with:
round . floor
You could also just call intValue on the Double result after calling floor.
http://docs.oracle.com/javase/6/docs/api/java/lang/Number.html#intValue%28%29

Java multiplication of negative numbers

In normal maths terms, -1756046391 * -1291488517 will equal 2267913749295792147.
When i enter the exact same equation in java, i get the answer: -1756046391 * -1291488517 = 19.
Can anyone shed any light on this?
Overflow.
Check out Integer.MAX_VALUE. An Integer in Java is a 32 bit 2s complement value. You can't exceed the MAX_VALUE.
When dealing with very large numbers, you need to make sure the data type you used is big enough to store that number. In java you have these primitive number types:
type: min: max:
byte -128 127
short -32768 32767
int -2,147,483,648 2,147,483,647
long -9,223,372,036,854,775,808 9,223,372,036,854,775,807
So as you can see, your number would just about fit into a long. But you're bound to go over that, so you should probably use the BigInt class instead:
http://docs.oracle.com/javase/6/docs/api/java/math/BigInteger.html
Either use longs as others said, or if that is not enough for your application, consider using BigInteger.
Post the exact code you used to reproduce this.
You are most likely using ints. Use longs, because 2267913749295792147 is too big to fit in an int.

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.

Categories

Resources