I am trying to convert a BigInteger number into binary. I use a while loop to reduce the BigInteger until it is equal to 1, taking the remainder as the loop runs.
The conditional for the loop is: (decimalNum.intValue()>1).
But the program only goes through the loop once and then thinks that the BigInteger is less/equal to 1 while in reality it is around 55193474935748.
Why is this happening?
("inBinary" is an ArrayList to hold the remainders from the loop.)
Here is the while loop:
while (decimalNum.intValue()>1){
inBinary.add(0, decimalNum.mod(new BigInteger("2")).intValue()); //Get remainder (0 or 1)
decimalNum = decimalNum.divide(new BigInteger("2")); //Reduce decimalNum
}
55,193,474,935,748 doesn't fit into an int: the largest int value is 231 - 1, i.e. 2,147,483,647, which is much smaller. So you get an integer overflow.
This is explained in the javadoc, BTW:
Converts this BigInteger to an int. This conversion is analogous to a narrowing primitive conversion from long to int as defined in section 5.1.3 of The Java™ Language Specification: if this 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 of the BigInteger value as well as return a result with the opposite sign.
If you want to compare a BigInteger to 1, then use
decimalNum.compareTo(BigInteger.ONE) > 0
To get the binary string value of your BigInteger, you could just do
bigInteger.toString(2);
EDIT : As mentionned in the comments by #VinceEmigh, converting BigInteger to int might lead to overflow.
Related
How can I create a jshortarray with 545460846912 elements
retval = env->NewShortArray((long) 545460846912); // allocate
~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~
..test.cpp:296:42: warning: implicit conversion from 'long' to 'jsize' (aka 'int') changes value from 545460846912 to 320 [-Wconstant-conversion]
env->SetShortArrayRegion(retval, 0 , (long) 545460846912, (short const *)b);
~~~~~~~~~~~~~~~~~~~ ^~
Try to mimic this code
int nGetEncoderFrameSize = (int) LibSpeex.nGetEncoderFrameSize(nInitSpxEncoder);
and it returns 545460846912 for my file
I need to make an short array with that size
short[] sArr = new short[nGetEncoderFrameSize];
and then call it:
long nEncodeBuffer = LibSpeex.nEncodeBuffer(nInitSpxEncoder, sArr, bArr, 65536);
Is it possible to create that big jshortArray?
How can I solve it?
How can I create a jshortarray with 545460846912 elements
You can't.
Per the Java 9 Language Specification (bolding mine):
Arrays must be indexed by int values; short, byte, or char values may also be used as index values because they are subjected to unary numeric promotion (§5.6.1) and become int values.
An attempt to access an array component with a long index value results in a compile-time error.
All array accesses are checked at run time; an attempt to use an index that is less than zero or greater than or equal to the length of the array causes an ArrayIndexOutOfBoundsException to be thrown.
The wording for Java 17 is identical.
Java int values are limited in range to (again, bolding mine):
4.2.1. Integral Types and Values
The values of the integral types are integers in the following ranges:
For byte, from -128 to 127, inclusive
For short, from -32768 to 32767, inclusive
For int, from -2147483648 to 2147483647, inclusive
For long, from -9223372036854775808 to 9223372036854775807, inclusive
For char, from '\u0000' to '\uffff' inclusive, that is, from 0 to 65535
2147483647 is smaller than 545460846912.
Why isn't there any function in the standard library of Kotlin/Java for taking the absolute value of a Byte/byte variable? I'm I missing something?
Math.abs() is only defined for int, long, double and float.
For context: in the audio world you can run easily into byte arrays representing the amplitude. I'm interested in calculating the average of the absolute values of a byte array. For e.g see this listener related to Visualizer in Android.
I know I can cast it to an integer and take the absolute value of that, but I would still be interested why is this not predefined.
The operations in java.lang.Math are in line with all other arithmetic operations in Java. Integer operations always work in either, 64 bit long or 32 bit int.
As stated in JLS, §4.2.2. Integer Operations
If an integer operator other than a shift operator has at least one operand of type long, then the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long. If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion (§5.6).
Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of type int. If either operand is not an int, it is first widened to type int by numeric promotion.
In other words, not even the following, equivalent to abs, would compile:
byte a = 42, absA = a < 0? -a: a;
as the numeric operation -a will promote a to int before negating.
It’s important that a cast of the result to byte would not be a lossless operation here. The byte datatype has a value range from -128 to +127, so if the value is -128, its absolute value +128 is outside the byte value range and a cast to byte would cause an overflow to -127.
Therefore, to have a correct and efficient calculation, you should do as always in Java when it comes to byte, short, or char calculations, calculate everything using int and only cast the final result back to your data type. When you want to calculate the average, you have to calculate the sum using int anyway (or even long if you have more than 16777215 array elements).
byte[] array // e.g. test case: = { 1, -1, -128, 127 };
int sum = 0;
for(byte b: array) sum += Math.abs(b);
int average = sum/array.length;
// if you really need a byte result
byte byteAverage = average == 128? 127: (byte)average;
I don’t know about Kotlin, but in Java, the automatic promotion to int also works if the operand is of type Byte, so you don’t need to “cast it to an integer” to call Math.abs(int). You only have to deal with the fact that the result will be an int, as with all arithmetic operations on byte, short, char, or their wrapper types.
In java byte is signed between -128 and 127, corresponding as (unsigned) int: 0xFF & b between 128 .. 255, and 0 .. 127.
Math.abs is irrelevant here as probably unsigned byte values are assumed.
int[] bytesToInt(byte[] bs) {
int[] is = new int[bs.length];
Arrays.fill(is, i -> bs[i] & 0xFF);
return is;
}
byte byteAbs(byte b) {
return b >= 0? b : b == -128? 127 : -b;
}
byteAbs - given for completeness - reduces the range to 7 bits, and has the artefact that -128 maps to 127, as there is no 128.
Most inputs to the program work fine but when i use large numbers e.g. 20 the value is incorrect. Is there a way I could convert the decimal numbers and output them as binary? Thank you.
int n = Comp122.getInt("What number would you like to make a factorial?");
int factorial = 1;
for (int i = 1 ; i<=n ; i++) {
factorial*=i;
System.out.println(factorial);
}
You’re encountering integer overflow at 13!, which exceeds the largest number that an int can hold, which is 231 (about 2.1 x 109).
You can change the type of your variable from int to long, which can hold 263 (about 1.9 x 1019), but that too will exceed its limit at 20!
To handle arbitrarily large numbers, use the BigInteger class as your variable type. Your code would then something like:
BigInteger factorial = BigInteger.ONE;
for (int i = 2; i < n; i++) {
factorial = factorial.multiply(néw BigInteger(i + ""));
}
By the way, to output an integer as binary or hex:
System.out.println(Integer.toBinaryString(n));
System.out.println(Integer.toHexString(n));
n! becomes very big and probably Integer cannot hold it as Integer has a limitation of 2,147,483,647.
That's not the problem of output, but rather you hit an overflow.
If you have a infinite range of input that could potentially fit in a BigInteger, you could try BigInteger. Otherwise, probably you'd like to use some unlimited data structure such as String. And do the calculation digit by digit.
Something like: https://www.geeksforgeeks.org/multiply-large-numbers-represented-as-strings/
20 the value is incorrect?
value of 20! = 2,432,902,008,176,640,000.
In java, an integer can properly handle any positive value less than 2,147,483,648.
int | 4 bytes | Stores whole numbers from -2,147,483,648 to 2,147,483,647
So, using int you can not handle this type of big value.
long datatype can be used for factorials only for n <= 20.
For larger values of n, we can use the BigInteger class from the java.math package, which can hold values up to 2^Integer.MAX_VALUE:
This code:
System.out.println(Math.abs(Integer.MIN_VALUE));
Returns -2147483648
Should it not return the absolute value as 2147483648 ?
Integer.MIN_VALUE is -2147483648, but the highest value a 32 bit integer can contain is +2147483647. Attempting to represent +2147483648 in a 32 bit int will effectively "roll over" to -2147483648. This is because, when using signed integers, the two's complement binary representations of +2147483648 and -2147483648 are identical. This is not a problem, however, as +2147483648 is considered out of range.
For a little more reading on this matter, you might want to check out the Wikipedia article on Two's complement.
The behaviour you point out is indeed, counter-intuitive. However, this behaviour is the one specified by the javadoc for Math.abs(int):
If the argument is not negative, the argument is returned.
If the argument is negative, the negation of the argument is returned.
That is, Math.abs(int) should behave like the following Java code:
public static int abs(int x){
if (x >= 0) {
return x;
}
return -x;
}
That is, in the negative case, -x.
According to the JLS section 15.15.4, the -x is equal to (~x)+1, where ~ is the bitwise complement operator.
To check whether this sounds right, let's take -1 as example.
The integer value -1 is can be noted as 0xFFFFFFFF in hexadecimal in Java (check this out with a println or any other method). Taking -(-1) thus gives:
-(-1) = (~(0xFFFFFFFF)) + 1 = 0x00000000 + 1 = 0x00000001 = 1
So, it works.
Let us try now with Integer.MIN_VALUE . Knowing that the lowest integer can be represented by 0x80000000, that is, the first bit set to 1 and the 31 remaining bits set to 0, we have:
-(Integer.MIN_VALUE) = (~(0x80000000)) + 1 = 0x7FFFFFFF + 1
= 0x80000000 = Integer.MIN_VALUE
And this is why Math.abs(Integer.MIN_VALUE) returns Integer.MIN_VALUE. Also note that 0x7FFFFFFF is Integer.MAX_VALUE.
That said, how can we avoid problems due to this counter-intuitive return value in the future?
We could, as pointed out by #Bombe, cast our ints to long before. We, however, must either
cast them back into ints, which does not work because
Integer.MIN_VALUE == (int) Math.abs((long)Integer.MIN_VALUE).
Or continue with longs somehow hoping that we'll never call Math.abs(long) with a value equal to Long.MIN_VALUE, since we also have Math.abs(Long.MIN_VALUE) == Long.MIN_VALUE.
We can use BigIntegers everywhere, because BigInteger.abs() does indeed always return a positive value. This is a good alternative, though a bit slower than manipulating raw integer types.
We can write our own wrapper for Math.abs(int), like this:
/**
* Fail-fast wrapper for {#link Math#abs(int)}
* #param x
* #return the absolute value of x
* #throws ArithmeticException when a negative value would have been returned by {#link Math#abs(int)}
*/
public static int abs(int x) throws ArithmeticException {
if (x == Integer.MIN_VALUE) {
// fail instead of returning Integer.MAX_VALUE
// to prevent the occurrence of incorrect results in later computations
throw new ArithmeticException("Math.abs(Integer.MIN_VALUE)");
}
return Math.abs(x);
}
Use a integer bitwise AND to clear the high bit, ensuring that the result is non-negative: int positive = value & Integer.MAX_VALUE (essentially overflowing from Integer.MAX_VALUE to 0 instead of Integer.MIN_VALUE)
As a final note, this problem seems to be known for some time. See for example this entry about the corresponding findbugs rule.
Here is what Java doc says for Math.abs() in javadoc:
Note that if the argument is equal to
the value of Integer.MIN_VALUE, the
most negative representable int value,
the result is that same value, which
is negative.
To see the result that you are expecting, cast Integer.MIN_VALUE to long:
System.out.println(Math.abs((long) Integer.MIN_VALUE));
There is a fix to this in Java 15 will be a method to int and long. They will be present on the classes
java.lang.Math and java.lang.StrictMath
The methods.
public static int absExact(int a)
public static long absExact(long a)
If you pass
Integer.MIN_VALUE
OR
Long.MIN_VALUE
A Exception is thrown.
https://bugs.openjdk.java.net/browse/JDK-8241805
I would like to see if either Long.MIN_VALUE or Integer.MIN_VALUE is passed a positive value would be return and not a exception but.
2147483648 cannot be stored in an integer in java, its binary representation is the same as -2147483648.
But (int) 2147483648L == -2147483648 There is one negative number which has no positive equivalent so there is not positive value for it. You will see the same behaviour with Long.MAX_VALUE.
Math.abs doesn't work all the time with big numbers I use this little code logic that I learnt when I was 7 years old!
if(Num < 0){
Num = -(Num);
}
Hi i hav a little problem about some code that i can't give an explanation about the result i have.
//what happens?
public static void what() {
int number = 2147483647;
System.out.println(number + 33);
}
//Here is my solution for the probleme
public static void what() {
long number = 2147483647;
System.out.println(number + 33);
}
The first code with the int number as variable gives me -2147483616 as result. So when i change the int to long i get the good result expected. So question is who can help me give and explanation of why int number + 33 = -2147483616
Java integers are based on 32 Bits. The first bit is kept for the sign (+ = 0 / - = 1).
So 2147483647 equals 01111111 11111111 11111111 11111111.
Adding more will force the value to turn to negative because the first bit is turned into a 1.
10000000 00000000 00000000 00000000 equals -2147483648.
The remaining 32 you are adding to -2147483648 brings you to your result of -2147483616.
The primitive int type has a maximum value of 2147483647, which is what you are setting number to. When anything is added to this value the int type cannot represent it correctly and 'wraps' around, becoming a negative number.
The maximum value of the long type is 9223372036854775807 so the second code snippet works fine because long can hold that value with no problem.
You have reached the maximum of the primitive type int (2147483647).
If int overflows, it goes back to the minimum value (-2147483648) and continues from there.
Consider the calculation of the second snippet, and what the result actually means.
long number = 2147483647;
number += 33;
The result in decimal is 2147483680, in hexadecimal (which more easily shows what the value means) it is 0x80000020.
For the first snippet, the result in hexacimal is also 0x80000020, because the result of arithmetic with the int type is the low 32 bits of the "full" result. What's different is the interpretation: as an int, 0x80000020 has the top bit set, and the top bit has a "weight" of -231, so this result is interpreted as -231 + 32 (a negative number). As a long, the 32nd bit is just a normal bit with a weight of 231 and the result is interpreted as 231 + 32.
The primitive type int is a 32-bit integer that can only store from -2^31 to 2^31 - 1 whereas long is a 64-bit integer so it can obviously store a much larger value.
When we calculate the capacity of int, it goes from -2147483648 to 2147483647.
Now you are wondering.. why is it that when the number exceeds the limit and I add 33 to it, it will become -2147483616?
This is because the data sort of "reset" after exceeding its limit.
Thus, 2147483647 + 1 will lead to -2147483648. From here, you can see that -2147483648 + 32 will lead to the value in your example which is -2147483616.
Some extra info below:
Unless you really need to use a number that is greater than the capacity of int, always use int as it takes up less memory space.
Also, should your number be bigger than long, consider using BigInteger.
Hope this helps!