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
Related
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:
So I have been at this for hours, and I'm honestly completely stuck. I've wrote a for loop that counts the amount of numbers in an integer, but I've found that the divisor value changes once i enter a number above 10 digits, and I can't figure out why. I've searched the internet to no avail, so I would appreciate any help or tips if you have any. Thank you!
public static int getNumberOfDigits(long creditCardNumber)
{
//problem with 0's at beginning and more than 10 digits
int nDigitsInCard = 0;
int divisor = (int) creditCardNumber;
for(int i = 0; i <= creditCardNumber; i++){
while(divisor!=0){
divisor/=10;
++nDigitsInCard;
}
}
// return the number of digits in nDigitsInCard
return nDigitsInCard;
}
ints can't hold numbers greater than 2,147,483,647. You need to stick to longs to work with larger numbers.
Integers can only hold numbers up to 2 ^ 32 - 1. Also, why are you casting the input parameter to an integer?
Another thing is that you are counting the number of digits in every number leading up to divisor since you are looping from 0 all the way up to creditCardNumber in the for(int i = 0; i <= creditCardNumber; i++){ ... }. So for example 10000 would return the number of digits in 1, the number of digits in 2, all the way up to 10000.
Lastly, the whole function can be done in one line with
return Long.toString(creditCardNumber).length();
or
return creditCardNumber.toString().length();
if you change creditCardNumber to a Long instead of a long, but you would have to call it with an l suffix at the end.
If you want something even shorter, you can do
return (creditCardNumber+"").length();
When you have the number greater than 10 digits, the conversion to an integer doesn't complete because the integer can't hold valures greater than 2^31 - 1, or 2,147,483,647, which is a number with only 10 digits. I recommend sticking with long.
We tried just for fun to create a for loop like below. We assumed that the number we get would be very high but we got 0. Why is it 0 and not something big?
We even tried it with a long because we thought it might be bigger than a int.
Thanks in advance.
private static void calculate() {
int currentSolution = 1;
for (int i = 1; i < 100; i++) {
currentSolution *= i;
}
System.out.println(currentSolution);
}
Your int is wrapping round to -2147483648 when it reaches +2147483647.
By an amazing coincidence1, a multiplication by zero is introduced into your product.
See for yourself: write
if (currentSolution == 0){
// What is the value of i?
}
You'll need a BigInteger to evaluate 100!.
1 Really it's not that amazing: it's just that 100! has 232 as a factor.
Your for loop calculates the factorial of 100, i.e. 1 * 2 * 3 * ... * 99 * 100, also written as 100! which equals 9.332621544×10157
The range of int is -2,147,483,648 to 2,147,483,647 and the range of long is -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807, so with a number that is 10157 you've hit multiplication overflow long before you even get close to the end of the for loop.
The overflow eventually results in all bits eventually zeroing out, thus producing the result 0.
Your datatypes are too small, even if you use long, so you cannot do this calculation with basic types. So you get an overflow, where the values become negative, and at some point 0. Therefore, the result is still zero after every loop.
You can see that by printing the currentSolution in the loop.
In order to get the correct solution, try using BigInteger:
public static void calculate() {
BigInteger currentSolution = BigInteger.valueOf(1);
for (int i = 1; i < 100; i++) {
currentSolution = currentSolution.multiply(BigInteger.valueOf(i));
}
System.out.println(currentSolution);
}
This outputs the correct solution: 933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000
You re basically calculating 100!, which is approximately 9.3e+157, whereas a long maximum value is 2^64 -1 so approximately 1.8e+19.
It cant fit, thats why you have 0.
This function is from java.util.Random. It returns a pseudorandom int uniformly distributed between 0 and the given n. Unfortunately I did not get it.
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n-1) < 0);
return val;
}
My questions are:
Why does it treat the case where n is a power of two specially ? Is it just for performance ?
Why doest it reject numbers that bits - val + (n-1) < 0 ?
It does this in order to assure an uniform distribution of values between 0 and n. You might be tempted to do something like:
int x = rand.nextInt() % n;
but this will alter the distribution of values, unless n is a divisor of 2^31, i.e. a power of 2. This is because the modulo operator would produce equivalence classes whose size is not the same.
For instance, let's suppose that nextInt() generates an integer between 0 and 6 inclusive and you want to draw 0,1 or 2. Easy, right?
int x = rand.nextInt() % 3;
No. Let's see why:
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0
So you have 3 values that map on 0 and only 2 values that map on 1 and 2. You have a bias now, as 0 is more likely to be returned than 1 or 2.
As always, the javadoc documents this behaviour:
The hedge "approximately" is used in the foregoing description only
because the next method is only approximately an unbiased source of
independently chosen bits. If it were a perfect source of randomly
chosen bits, then the algorithm shown would choose int values from the
stated range with perfect uniformity.
The algorithm is slightly tricky. It rejects values that would result
in an uneven distribution (due to the fact that 2^31 is not divisible
by n). The probability of a value being rejected depends on n. The
worst case is n=2^30+1, for which the probability of a reject is 1/2,
and the expected number of iterations before the loop terminates is 2.
The algorithm treats the case where n is a power of two specially: it
returns the correct number of high-order bits from the underlying
pseudo-random number generator. In the absence of special treatment,
the correct number of low-order bits would be returned. Linear
congruential pseudo-random number generators such as the one
implemented by this class are known to have short periods in the
sequence of values of their low-order bits. Thus, this special case
greatly increases the length of the sequence of values returned by
successive calls to this method if n is a small power of two.
The emphasis is mine.
next generates random bits.
When n is a power of 2, a random integer in that range can be generated just by generating random bits (I assume that always generating 31 and throwing some away is for reproducibility). This code path is simpler and I guess it's a more commonly used case so it's worth making a special "fast path" for this case.
When n isn't a power of 2, it throws away numbers at the "top" of the range so that the random number is evenly distributed. E.g. imagine we had n=3, and imagine we were using 3 bits rather than 31 bits. So bits is a randomly generated number between 0 and 7. How can you generate a fair random number there? Answer: if bits is 6 or 7, we throw it away and generate a new one.
This question already has answers here:
Why do these two multiplication operations give different results?
(2 answers)
Closed 9 years ago.
Now signed_int max value is 2,147,483,647 i.e. 2^31 and 1 bit is sign bit, so
when I run long a = 2,147,483,647 + 1;
It gives a = -2,147,483,648 as answer.. This hold good.
But, 24*60*60*1000*1000 = 86400000000 (actually)...
In java, 24*60*60*1000*1000 it equals to 500654080..
I understand that it is because of overflow in integer, but what processing made this value come, What logic was used to get that number by Java. I also refered here.
Multiplication is executed from left to right like this
int x = 24 * 60;
x = x * 60;
x = x * 1000;
x = x * 1000;
first 3 operations produce 86400000 which still fits into Integer.MAX_VALUE. But the last operation produces 86400000000 which is 0x141dd76000 in hex. Bytes above 4 are truncated and we get 0x1dd76000. If we print it
System.out.println(0x1dd76000);
the result will be
500654080
This is quite subtle: when writing long a = 2147483647 + 1, the right hand side is computed first using ints since you have supplied int literals. But that will clock round to a negative (due to overflow) before being converted to a long. So the promotion from int to long is too late for you.
To circumvent this behaviour, you need to promote at least one of the arguments to a long literal by suffixing an L.
This applies to all arithmetic operations using literals (i.e. also your multiplication): you need to promote one of them to a long type.
The fact that your multiplication answer is 500654080 can be seen by looking at
long n = 24L*60*60*1000*1000;
long m = n % 4294967296L; /* % is extracting the int part so m is 500654080
n.b. 4294967296L is 2^32 (using OP notation, not XOR). */
What's happening here is that you are going 'round and round the clock' with the int type. Yes, you are losing the carry bits but that doesn't matter with multiplication.
As the range of int is -2,147,483,648 to 2,147,483,647.
So, when you keep on adding numbers and its exceed the maximum limit it start gain from the left most number i.e. -2,147,483,648, as it works as a cycle. That you had already mentioned in your question.
Similarly when you are computing 24*60*60*1000*1000 which should result 86400000000 as per Maths.
But actually what happens is somehow as follows:
86400000000 can be written as 2147483647+2147483647+2147483647+2147483647+..36 times+500654080
So, after adding 2147483647 for 40 times results 0 and then 500654080 is left which ultimately results in 500654080.
I hope its clear to you.
Add L in your multiplicatoin. If you add L than it multiply you in Long range otherwise in Integer range which overflow. Try to multiply like this.
24L*60*60*1000*1000
This give you a right answer.
An Integer is 32 bit long. Lets take for example a number that is 4 bit long for the sake of simplicity.
It's max positive value would be:
0111 = 7 (first bit is for sign; 0 means positive, 1 means negative)
0000 = 0
It's min negative value would be:
1111 = -8 (first bit is for sign)
1000 = -1
Now, if we call this type fbit, fbit_max is equal to 7.
fbit_max + 1 = -8
because bitwise 0111 + 1 = 1111
Therefore, the span of fbit_min to fbit_max is 16. From -8 to 7.
If you would multiply something like 7*10 and store it in fbit, the result would be:
fbit number = 7 * 10 (actually 70)
fbit number = 7 (to get to from zero to max) + 16 (min to max) + 16 (min to max) + 16 (min to max) + 15 (the rest)
fbit number = 6
24*60*60*1000*1000 = 86400000000
Using MOD as follows: 86400000000 % 2147483648 = 500654080