I am trying to write a code which raises 2 to
the powers of 0, 1, 2. 3. 4, .... n
For example for 31 it would reproduce the following results:
1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192
16384 32768 65536 131072 262144 524288 1048576 2097152
4194304 8388608 16777216 33554432 67108864 134217728
268435456 536870912 1073741824 2147483648
I have written the following code:
public class Powersof2 {
public static void printPowersOf2(int n) {
if (n >= 0 && n <= 64) {
for (int i = 0 ; i <= n ; i++) {
System.out.print( Math.pow(2, i) + " ");
}
} else {
System.out.println("You have input an invalid value");
return;
}
}
public static void main(String[] args) {
printPowersOf2(31);
System.out.println();
}
}
However, it produces the following result instead:
1.0 2.0 4.0 8.0 16.0 32.0 64.0 128.0 256.0 512.0
1024.0 2048.0 4096.0 8192.0 16384.0 32768.0 65536.0
131072.0 262144.0 524288.0 1048576.0 2097152.0 4194304.0
8388608.0 1.6777216E7 3.3554432E7 6.7108864E7 1.34217728E8
2.68435456E8 5.36870912E8 1.073741824E9 2.147483648E9
How can I fix that?
Also I have another question
When I input larger values for n such as 62 the values start to be the same. For example 62 gives:
1 2 4 8 16 32 64 128 256 512 1024 2048 4096
8192 16384 32768 65536 131072 262144 524288 1048576
2097152 4194304 8388608 16777216 33554432 67108864 134217728
268435456 536870912 1073741824 2147483647 2147483647
2147483647 2147483647 2147483647 2147483647 2147483647
2147483647 2147483647 2147483647 2147483647 2147483647
2147483647 2147483647 2147483647 2147483647 2147483647
2147483647 2147483647 2147483647 2147483647 2147483647
2147483647 2147483647 2147483647 2147483647 2147483647
2147483647 2147483647 2147483647 2147483647 2147483647
how can I fix this issue?
Since Math.pow returns a double while you are looking for an integer, consider using a simple bit trick for raising 2 to power n like this:
1L << n
The reason behind this trick is the same as that behind multiplying by powers of ten in the decimal system by writing additional zeros after the number.
This works for ns between 0 and 63, and produce a long:
for (int i = 0 ; i <= n ; i++) {
System.out.print( (1L << i) + " ");
}
Math.pow() always returns doubles. You need to cast it to an int. System.out.print((int)Math.pow(2, i)+ " ");
Because public static double pow(double a, double b) return a double. And Java double is 64 bit IEE754 number with precision, so you see the decimal points in the end.
You can cast it to int as (int)Math.pow(2, i)but be aware that for 2^31 onwards you will not get expected results because int range is from -2^31 to +2^31.
** First Solution:**
So, to get your expected result to get power up to 63, cast to long because Java long has range from -2^63 to +2^63
for (int i = 0; i <= 64; i++) {
System.out.println((long)Math.pow(2, i));
}
You query about result as so many 2147483647 :
This is called as Narrowing, when a bigger container value is casted to smaller container value.
Below excerpt from Java Language Specification - $5.1.3 Narrowing Primitive Conversion, for rules governing primitive narrowing.
So, after power of 31, all the higher bits (32, 33....) are discarded, and hence you always result of 31 bits i.e. 2^31.
In you case, as per JLS, your "integral type T" was int, so all bits are discarded but the n lowest order bits (which means 31, because you are narrowing to int)
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.
A comprehensive solution: (as per discussion going around)
Primitive data types has range limitation, so there are BigInteger, BigDecimal which provides arbitrarily long values and precision. So, you can use BigInteger to get accurate result.
Notice that if you Java's long then for 2^63 you get result as 9223372036854775807 while as per Power of two Wiki result should be 9223372036854775808 which you get when you use BigInteger
Bottom line: Use BigInteger to get desired range of power of 2.
Hope this covers all your concern and give you scalable solution.
for (int i = 0; i <= 64; i++) {
//System.out.println((long)Math.pow(2, i));
System.out.println(BigInteger.valueOf(2).pow(i)); //Gives exact result as per Wiki information
}
These are the powers of 2 through 2^31, just in the default output format of a double. With lower values, it will append .0, and with higher values, it's in pseudo-scientific notation. E.g. 1.6777216E7 means 1.677216 x 107, or 1,677,216. The double is returned from Math.pow.
You may find an integer type data type better formatted for your purpose. Use long, because int isn't quite big enough to store 2^31.
long product = 1;
for (int i = 0 ; i <= n ; i++)
{
System.out.print( product + " ");
product *= 2; // Equivalent: product <<= 1;
}
i could have used below code part, instead math.pow() , i am always scared of type conversion
int num=1;
for(int i=0;i<n;i++){
System.out.println(num);
num=num*2;
}
but as suggested it can not go beyond 31 . it is limit of int data type. try BigInteger if you want to print more
With Java 8 you can simply use the following stream:
IntStream.range(0, 32)
.map(value -> 1 << value)
.forEach(value -> System.out.println("value = " + value));
Also, the same is applicable to LongStream.
Related
This question already has answers here:
Multiplication of Integer.MAX_VALUE in Java [duplicate]
(3 answers)
Closed 4 years ago.
I was looking for a value of i where i==i+1 should always be true. Some others used double and float to find a solution to the problem.
I was trying to answer to a question on stack overflow. And thought about integers, trying to see if that could be possible too.
But while manipulating Integer.MAX_VALUE and Integer.MIN_VALUE many times, I found this strange behavior:
Integer.MAX_VALUE + 1 == Integer.MIN_VALUE
But Integer.MAX_VALUE * 2 == -2 and Integer.MAX_VALUE * 4 == -4
This happens only if I use even values like (2,4,6,8,10,12...). When I use odd values except 1, this happens:
Integer.MAX_VALUE * n == Integer.MAX_VALUE - n + 1 where n != Integer.MIN_VALUE and n > Integer.MIN_VALUE
Why is this behaving so? Is there something I am missing?
EDIT: I saw someone flagging the question as duplicate but navigating to the referred link, my question is different.
If it overflows, it goes back to the minimum value and continues from >there. If it underflows, it goes back to the maximum value and continues >from there.
I've carefully read answers from there but none of them explained why:
Integer.MAX_VALUE*x should be -x if x is an even number and Integer.MAX_VALUE*y should be Integer.MAX_VALUE-y+1 if y is an odd number.
That's exactly what is confusing me the most.
That's because Java's signed integers follow two's complement representation.
In a two's complement representation, negative numbers are represented as an N-bit complement of their corresponding positive value, i.e. their sum modulo 2n is 0.
Integer.MAX_VALUE is 2147483647 (hex 0x7FFFFFFF).
When multiplied, it overflows, and what remains is the lowest 32 bits (i.e. modulo 232):
0x7FFFFFFF * 2 = 0x0FFFFFFFE (mod32 = 0xFFFFFFFE = -2)
0x7FFFFFFF * 3 = 0x17FFFFFFD (mod32 = 0x7FFFFFFD = 2147483645)
0x7FFFFFFF * 4 = 0x1FFFFFFFC (mod32 = 0xFFFFFFFC = -4)
0x7FFFFFFF * 5 = 0x27FFFFFFB (mod32 = 0x7FFFFFFB = 2147483643)
0x7FFFFFFF * 6 = 0x2FFFFFFFA (mod32 = 0xFFFFFFFA = -6)
0x7FFFFFFF * 7 = 0x37FFFFFF9 (mod32 = 0x7FFFFFF9 = 2147483641)
An interesting property of two's complement representation is that the highest bit corresponds to the sign of the value.
Notice how the leftmost 7 results in alternating 0/1 bit 31. That bit happens to control the sign of the result, hence the alternating sign.
Why 0x7FFFFFFF * 2 is -2 is because 0x7FFFFFFF in a 31-bit representation (the largest possible representation without overflowing) is -1. And -1 * 2 = -2.
You can achieve a similar result if you take Long.MAX_VALUE and cast the result to int:
long x = Long.MAX_VALUE;
for (int i = 2; i < 8; i++) {
System.out.println((int)(x * i));
}
Just prints:
-2
-3
-4
-5
-6
-7
Now bit 31 isn't alternating anymore so we get stable results.
2147483647 is the max value, now try executing below set of instructions:
int i = 2147483647;
i++;
System.out.println(i);//prints -2147483647 as the 32 bit limit exceeds
binary equivalent of 2147483647 is 01111111111111111111111111111111
binary equivalent of 2 is 00000000000000000000000000000010
binary addition is 110000000000000000000000000000000
NOTE: The last bit at left stands for sign, int being 32 bit signed integer
thus, the number becomes -2147483647
i++;
System.out.println(i); // prints -2147483647
on the same lines, 2147483647 * 2 is actually -> 2147483647 + 2147483647
int j = 2147483647;
j += 2147483647;
System.out.println(j); // prints -2
and thus you answer.
now when you do 2147483647 * 3,
it is:
2147483647 + 2147483647 + 2147483647 = -2 + 2147483647 = 2147483645
In Java, create a do-while loop that starts at 2, and displays the number squared on each line while the number is less than 1,000,000. And this is what I have:
int k = 2;
do {
System.out.println(k);
k *= k;
} while(k < 1000000);
The problem is the output, somehow it is getting stuck at 0 and infinitely looping through 0 to print those out? I don't believe it is due to the fact that the number is out of int range, since a 32 bit number's range is around +/- 2 billion... But when I switch up the data type of k to be long everything works fine... Why is this?
It really is due to int. The sequence produced this way is
2
4
16
256
65536
0
And then it remains zero. Note that it never rises above 1000000.
With a long, the number after 65536 would be 4294967296 (which does not fit in an int, but does fit in a long), so it stops.
This is perhaps more obvious in hexadecimal, the sequence then reads (with sufficiently long integers)
2
4
0x10
0x100
0x10000
0x100000000
An int can only keep the lowest 8 hexadecimal digits, so 0x100000000 becomes 0.
Your code to print squares should be
int k = 2;
do {
System.out.println(k*k);
k++;
}while(k < 1000000);
As you are storing the result in same variable, your output is growing exponentially
I think much explanation is not required, why below calculation gives result as 1?
int a = 2147483647;
int b = 2147483647;
int c = a * b;
long d = a * b;
double e = a * b;
System.out.println(c); //1
System.out.println(d); //1
System.out.println(e); //1.0
The binary representation of the integer number 2147483647 is as following:
01111111 11111111 11111111 11111111
Multiplying this with itself results in the number 4611686014132420609 whose binary representation is:
00111111 11111111 11111111 11111111 00000000 00000000 00000000 00000001
This is too large for the int type which has only 32 bits. The multiplication of a * b is done as an integer multiplication only, regardless of the variable's type to which the result is assigned (which might do a widening conversion, but only after the multiplication).
So, the result simply cuts off all bits that do not fit into the 32 bits, leaving only the following result:
00000000 00000000 00000000 00000001
And this simply is the value 1.
If you want keep the information, you must do the multiplication with the long type which has 64 bits:
long a = 2147483647;
long b = 2147483647;
long mult = a * b;
System.out.println((int) mult); // 1
System.out.println(mult); // 4611686014132420609
System.out.println((double) mult); // 4.6116860141324206E18
If you need more bits for a calculation you might consider BigInteger (for integral numbers) or BigDecimal (for decmial numbers).
2147483647 * 2147483647 = 4611686014132420609
Which in Hexa = 3FFFFFFF 00000001, after truncation only 00000001 remains which represents 1.
First of all, the reason that the three attempts all give the same answer is that they are all performing 32 bit multiplications and the multiplication overflows, resulting in "loss of information". The overflow / loss of information happens before the value of the RHS1 expression is assigned to the variable on the LHS.
In the 2nd and 3rd case you could cause the expression to be evaluated using 64 bit or floating point:
int c = a * b;
long d = ((long) a) * b;
double e = ((double) a) * b;
and you would not get overflow.
As to why you get overflow in the 32 bit case, that is simple. The result is larger than 32 bits. The other answers explain why the answer is 1.
Just for fun, here is an informal proof.
Assume that we are talking about a modular number system with numbers in the range 2N-1 to 2N-1 - 1. In such a number system, X * 2N maps to zero ... for all integers X.
If we multiply the max value by itself we get
(2N-1 - 1) * (2N-1 - 1)
-> 22N-2 - 2 * 2N-1 + 1
-> 22N-2 - 2N + 1
Now map that into the original range:
22N-2 maps to 0
2N maps 0
1 maps to 1
0 + 0 + 0 -> 1
1 - LHS == left hand side, RHS == right hand side.
What you are seeing is simply the result of integer overflow, which follows this rule:
Integer.MAX_VALUE + 1 = Integer.MIN_VALUE
One way to see what is happening is to contrive Java's int type as ranging from -7 to 7, with the same rule still applying. Let's see what happens when we multiply 7*7:
7 + 7 = 14 -> -2 (7 x 2)
-2 + 7 = 5 (7 x 3)
5 + 7 = 12 -> -4 (7 x 4)
-4 + 7 = 3 (7 x 5)
3 + 7 = 10 -> -6 (7 x 6)
-6 + 7 = 1 (7 x 7, one is leftover)
The same thing is happening in your code, with 2147483647 overflowing according to:
2147483647 + 1 = -2147483648
Because:
2147483647 * 2147483647 = 4611686014132420609
Integer capacity = 4294967295
4611686014132420609 % 4294967295 = 1
integer has only 3 byte memory allocation as well as double has 8 byte memory allocation your multiplication is so large than its give only starting which has (0000 0001)2 = 1
Hey I have a case where I tried to run this on REPL:
(1 to 100).toList.reduce(_*_)
And it Returned me 0. I did not understand this behavior. If the Int has been overflowed it should have returned any negative or positive number. I got curious hence I tried this:
(1 to 100).toList.fold(1)(_*_)
It still returned me 0
Then I tried this:
(1 to 100).toList.fold(1)((a,b) => { println(s"dd::::$a:::$b"); a*b })
It returns me :
scala> res0.toList.fold(1)((a,b) => { println(s"dd::::$a:::$b"); a*b })
dd::::1:::1
dd::::1:::2
dd::::2:::3
dd::::6:::4
dd::::24:::5
dd::::120:::6
dd::::720:::7
dd::::5040:::8
dd::::40320:::9
dd::::362880:::10
dd::::3628800:::11
dd::::39916800:::12
dd::::479001600:::13
dd::::1932053504:::14
dd::::1278945280:::15
dd::::2004310016:::16
dd::::2004189184:::17
dd::::-288522240:::18
dd::::-898433024:::19
dd::::109641728:::20
dd::::-2102132736:::21
dd::::-1195114496:::22
dd::::-522715136:::23
dd::::862453760:::24
dd::::-775946240:::25
dd::::2076180480:::26
dd::::-1853882368:::27
dd::::1484783616:::28
dd::::-1375731712:::29
dd::::-1241513984:::30
dd::::1409286144:::31
dd::::738197504:::32
dd::::-2147483648:::33
dd::::-2147483648:::34
dd::::0:::35
dd::::0:::36
dd::::0:::37
dd::::0:::38
dd::::0:::39
dd::::0:::40
dd::::0:::41
dd::::0:::42
dd::::0:::43
dd::::0:::44
dd::::0:::45
dd::::0:::46
dd::::0:::47
dd::::0:::48
dd::::0:::49
dd::::0:::50
dd::::0:::51
dd::::0:::52
dd::::0:::53
dd::::0:::54
dd::::0:::55
dd::::0:::56
dd::::0:::57
dd::::0:::58
dd::::0:::59
dd::::0:::60
dd::::0:::61
dd::::0:::62
dd::::0:::63
dd::::0:::64
dd::::0:::65
dd::::0:::66
dd::::0:::67
dd::::0:::68
dd::::0:::69
dd::::0:::70
dd::::0:::71
dd::::0:::72
dd::::0:::73
dd::::0:::74
dd::::0:::75
dd::::0:::76
dd::::0:::77
dd::::0:::78
dd::::0:::79
dd::::0:::80
dd::::0:::81
dd::::0:::82
dd::::0:::83
dd::::0:::84
dd::::0:::85
dd::::0:::86
dd::::0:::87
dd::::0:::88
dd::::0:::89
dd::::0:::90
dd::::0:::91
dd::::0:::92
dd::::0:::93
dd::::0:::94
dd::::0:::95
dd::::0:::96
dd::::0:::97
dd::::0:::98
dd::::0:::99
dd::::0:::100
res5: Int = 0
I do not understand this behavior clearly. Could anyone please help !Thanks
I do not understand this behavior clearly
Generally, what you're experiencing is arithmetic overflow. If you want to pinpoint exactly why the 34th value returns 0, then doing the calculation by hand can help.
The result of the 33th product is -2147483648, which is:
64bit hex: 0xFFFFFFFF80000000
32bit hex: 0x80000000
64bit binary: 1111111111111111111111111111111110000000000000000000000000000000
32bit binary: 10000000000000000000000000000000
We multiply it by 34, we get:
64bit hex: 0xFFFFFFEF00000000
32bit hex: 0x00000000
64bit binary: 1111111111111111111111111110111100000000000000000000000000000000
32bit binary: 00000000000000000000000000000000
Since Int looks at the lower 32bit, you get 0. Everything on from here will result in 0 since that's the accumulators value and you're doing multiplication.
Execute the following to understand what is going on:
val x = Int.MinValue
x - 1 // = Int.MaxValue-1
x + x // = 0
x + x + x // = Int.MinValue
When you subtract from Int.MinValue you start from the max value. If you subtract abs(MinValue) from MinValue (MinValue * 2) you will be doing abs(MinValue) steps left from MaxValue which will bring you to 0.
This behaviour leads you to a situation in which MinValue * even number = 0 and MinValue * odd number = MinValue
Both behaviours occurred on lines 33-34, and of course as soon as one of you results is 0, all of your other results will be 0 as well.
In your output there is one line like: dd::::-2147483648:::34, which produces 0 as output. Hence all subsequent multiplications result in 0.
Reason being -2147483648 in minimum value of Int (Int.MinValue).
scala> Int.MinValue
res6: Int = -2147483648
If you try -2147483648 + -2147483648 in REPL, because of Int overflow, output will be 0. Now when you do -2147483648 * 34 it is equivalent to (-2147483648 + (-2147483648)) * 17, hence output is 0.
This question already has answers here:
How does Java handle integer underflows and overflows and how would you check for it?
(12 answers)
Closed 8 years ago.
I am writing a java program to output exponential powers of 2 (by the way, I cannot use Math.pow()), however at 2^31 and 2^32 I get something else. Also, I don't intend to accept negative integers.
My code:
class PrintPowersOf2 {
public static void main (String[] args) {
printPowersOf2(10);
printPowersOf2(5);
printPowersOf2(2);
printPowersOf2(-5);
printPowersOf2(30);
printPowersOf2(32);
}
public static void printPowersOf2 (int x) {
for(int i=0;i<x+1;i++) {
int y = exponent (i);
System.out.print(y);
if(!(i == x)) {
System.out.print(" ");
}
}
System.out.println();
}
static int exponent(int power) {
int output = 1;
for (int z=0; z<power; z++)
output *= 2;
return output;
}
}
The output I get is:
1 2 4 8 16 32 64 128 256 512 1024
1 2 4 8 16 32
1 2 4
1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 1073741824
1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 134217728 268435456 536870912 1073741824 -2147483648 0
An int is represented with 32 bits. Thus any value between -2^31 and 2^31-1 can be represented. Nothing out of this range.
You can use a long (64 bits), or a BigInteger (a datastructures that can represented all numbers up to the memory limit).
The disadvantage of using these structures (especially BigInteger) is that a CPU does not always offer instructions for arithmetic. Thus adding two BigInteger instances requires more time than doing this with an int or long. In case of a long, if the CPU is 32-bit, it requires at least two instructions to process this.
On a sidenote. A CPU offers a better way to calculate the powers of two: shift operations.
You can simply write:
long value = 0x01L << power;//power of two, all in one simple instruction.
This works as follow: a shift moves bits to the left. Thus if the original value is:
0001 1011 << 2
= 0110 1100
Shifting to the left in a binary representation is arithmetically the same as multiplying with two.
In general,
byte 8 bits, short 16 bits, int 32 bits, long 64 bits
For Integer(int) you can store a value in between -2^31 and 2^31 i.e., from -2,147,483,648 to 2,147,483,647
If you really want to calculate powers of 2 without any limitations (atleast as per theory), you can use strings and make multiplications accordingly.
Edit:
As Commusoft suggested, BigIntegers can also be used which improves performance over Strings.