0

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?

5
  • 1
    Since int has only of 32 bits, and its most significant bit is used for the sign, powers above 31 cannot be expressed in a Java int. Commented Jul 9, 2015 at 17:54
  • @dablinkenlight is there any way around that? make it 64 bit? Commented Jul 9, 2015 at 17:58
  • 2
    My answer lets you go up to 63 bits, because 1L is long. 64-th bit is a sign bit, though, so in order to get beyond 63 you would need to use BigInteger - for example, like this: BigInteger.valueOf(2).pow(i). Commented Jul 9, 2015 at 18:00
  • @dasblinkenlight I understand the concept of long but what is Biginteger? Commented Jul 9, 2015 at 18:02
  • 1
    BigInteger is a class for representing arbitrarily large integer values. Commented Jul 9, 2015 at 18:12

6 Answers 6

3

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) + "   ");
}
Sign up to request clarification or add additional context in comments.

Comments

2

Math.pow() always returns doubles. You need to cast it to an int. System.out.print((int)Math.pow(2, i)+ " ");

2 Comments

Thanks, Are there any other ways to raise powers? @eagras
@JackStew not any that i know of. I always use Math.pow
1

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
        }

3 Comments

can you give the question a second view. I added a thing. @hagrawal
@JackStew Added, have a look. Please let me know in case of any question. Please do read JLS for narrowing rules.
@JackStew Check latest edit, I have tried to cover all your concerns.
1

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;
}

2 Comments

can I give the question a second view. I added a second part. @rgettman
If you were to cast the double to an int, and if the value is larger than the largest possible int, Integer.MAX_VALUE, which is 2^31 - 1 (2147483647), then the value is narrowed to Integer.MAX_VALUE. You could cast to long, or you could keep the product as a long.
0

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

1 Comment

Yeah but it isn't number times 2 it is 2 raised to number @Bhupi
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.