Weird for loop number in AndroidStudio/Flutter - java

I just played around in AndroidStudio and came across this number:
8198552921648689606
my code looks like this:
int x = 1;
for (int i = 0; i<64; i++)
{
x++;
x *= 10;
}
print(x);
For some reason it gets stuck on this weird number.
I expected it to jump around on the integer line but for all the numbers above 64 it just stays like this.
It only happens with the numbers 10 or 100 or 1000(or any factor of ten i would assume) as a factor and it happens in Java as well.
The numbers that it gets stuck on change depending on the type of bit system and the numbers used but it gets stuck all the time.
Seems to be a weird coincidence regarding the integer line but i would really like to know whats going on.
Update:
Seems to happen with even factors but not with odd ones. Still cant wrap my head around this though.

I don't understood quite well what you are trying to do, but here is what is happen:
First of all, if you want to follow the "transformation" of values in your 'x' variable, you should include the print statement inside the loop:
for (int i = 0; i<64; i++)
{
x++;
x *= 10;
print(x); // <- inserted in here
}
print(x);
Second, if you do this you should be able to see that scenario:
i
x
(after "x++")
after ( x *= 10)
1
1
2
20
2
20
21
210
3
210
211
2110
...
...
...
...
When i = 63 your x will be = 211111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110 (2.1*10^127). Notice that this number is way greater than the Java's int limit 2147483647

Related

Need some explanation to really understand how for loop/binary works in this specific example(JAVA)

public class fpNumbers {
public static void main(String args[]) {
int i;
double d = 0.1;
for(i = 1; i <= 20; i++) {
System.out.println(1.0 + d);
d = d / 10;
}
}
}
For the above code, the question is why does the result become 1,0 after a few iterations.
But before that I want to find out what is actually happening anyways. I understand how for loops work (at least I think so), but the i++ means +1 is added to i every turn. But why does i disappear after that and what's the reason for the System.out.println(1.0 + d); then.... 1.0 has nothing to do with i right and d is also d = d / 10? Doesn't make sense to me how a variable is itself divided by 10, shouldn't that create an infinite loop?
i does not disappear. If you add a System.out.println(i); after the for loop you will see i is 21.
A double can only have 15 decimal places. Everything less than 0.000000000000001 will not be stored by this primitive. After deviding 0.1 20 times it will just be zero. So don't be surprised if the console shows "1.0". You added 0 to 1.
Why should d = d/10 cause an infinite loop? The value will be divided by 10 exactly 1 time. If I have a bowl with an apple in it and replace the apple with itself cutted into 10 pieces I won't recieve infinite pieces, too.
The problem with the result becoming 1.0 after a few iterations is that double has 15 significant digits, which limits its precision.
After few iterations, you have a number 1.0000000000000001, which requires 16 significant digits and double can not represent it, so it "cuts" it.
If for example, you changed println() line to the following,
System.out.println(d);
You would see correct results, because these numbers require only 1 significant digit.
To learn more about double and significant digits, I would recommend
https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3
https://en.wikipedia.org/wiki/Significant_figures
https://en.wikipedia.org/wiki/Double-precision_floating-point_format
Secondly d = d / 10 wouldn't cause infinite loop.
Assignment operation works as follows: first, the right expression is evaluated, in your case d / 10 is computed, after that this value is assigned to the variable on the left.

Time complexity for two pieces of code

We've got 2 pieces of code:
int a = 3;
while (a <= n) {
a = a * a;
}
And:
public void foo(int n, int m) {
int i = m;
while (i > 100)
i = i / 3;
for (int k = i ; k >= 0; k--) {
for (int j = 1; j < n; j*=2)
System.out.print(k + "\t" + j);
System.out.println();
}
}
What is the time complexity of them?
I think that the first one is: O(logn), because it's progressing to N with power of 2.
So maybe it's O(log2n) ?
And the second one I believe is: O(nlog2n), because it's progressing with jumps of 2, and also running on the outer loop.
Am I right?
I believe, that first code will run in O(Log(LogN)) time. It's simple to understand in this way
Before first iteration you have 3 in power 1
After first iteration you have 3 in power 2
After second iteration you have 3 in power 4
After third iteration you have 3 in power 8
After fourth iteration you have 3 in power 16
and so on.
In the second code first piece of code will work in O(LogM) time, because you divide i by 3 every time. The second piece of code C times (C equals 100 in your case) will perform O(LogN) operations, because you multiply j by 2 every time, so it runs in O(CLogN), and you have complexity O(LogM + CLogN)
For the first one, it is indeed O(log(log(n))). Thanks to #MarounMaroun for the hint, I could find this:
l(k) = l(k-1)^2
l(0) = 3
Solving this system yields:
l(k) = 3^(2^k)
So, we are looking for such a k that satisfies l(k) = n. So simply solve that:
This means we found:
The second code is seems misleading. It looks like O(nlog(n)), but the outer loop limited to 100. So, if m < 100, then it obviously is O(mlog(n)). Otherwise, it kind of depends on where exactly m is. Consider these two:
m: 305 -> 101 -> 33
m: 300 -> 100
In the first case, the outer loop would run 33 times. Whereas the second case would cause 100 iterations. I'm not sure, but I think you can write this as being O(log(n)).

Sorting by least significant digit

I am trying to write a program that accepts an array of five four digit numbers and sorts the array based off the least significant digit. For example if the numbers were 1234, 5432, 4567, and 8978, the array would be sorted first by the last digit so the nest sort would be 5432, 1224, 4597, 8978. Then after it would be 1224, 5432, 8978, 4597. And so on until it is fully sorted.
I have wrote the code for displaying the array and part of it for sorting. I am not sure how to write the equations I need to compare each digit. This is my code for sorting by each digit so far:
public static void sortByDigit(int[] array, int size)
{
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size; j++)
{
}
for(i = 0; i < size; i++)
{
System.out.println(array[i]);
}
}
}
I am not sure what to put in the nested for loop. I think I need to use the modulus.
I just wrote this to separate the digits but I don't know how to swap the numbers or compare them.
int first = array[i]%10;
int second = (array[i]%100)/10;
int third = (array[i]%1000)/10;
int fourth = (array[i]%10000)/10;
Would this would go in the for loop?
It seems like your problem is mainly just getting the value of a digit at a certain index. Once you can do that, you should be able to formulate a solution.
Your hunch that you need modulus is absolutely correct. The modulo operator (%) returns the remainder on a given division operation. This means that saying 10 % 2 would equal 0, as there is no remainder. 10 % 3, however, would yield 1, as the remainder is one.
Given that quick background on modulus, we just need to figure out how to make a method that can grab a digit. Let's start with a general signature:
public int getValueAtIdx(int value, int idx){
}
So, if we call getValueAtIdx(145, 2), it should return 1 (assuming that the index starts at the least significant digit). If we call getValueAtIdx(562354, 3), it should return 2. You get the idea.
Alright, so let's start by using figuring out how to do this on a simple case. Let's say we call getValueAtIdx(27, 0). Using modulus, we should be able to grab that 7. Our equation is 27 % x = 7, and we just need to determine x. So 27 divided by what will give us a remainder of 7? 10, of course! That makes our equation 27 % 10 = 7.
Now that's all find and dandy, but how does 10 relate to 0? Well, let's try and grab the value at index 1 this time (2), and see if we can't figure it out. With what we did last time, we should have something like 27 % x = 27 (WARNING: There is a rabbit-hole here where you could think x should be 5, but upon further examination it can be found that only works in this case). What if we take the 10 we used earlier, but square it (index+1)? That would give us 27 % 100 = 27. Then all we have to do is divide by 10 and we're good.
So what would that look like in the function we are making?
public int getValueAtIdx(int value, int idx){
int modDivisor = (int) Math.pow(10, (idx+1));
int remainder = value % modDivisor;
int digit = remainder / (modDivisor / 10);
return digit;
}
Ok, so let's to back to the more complicated example: getValueAtIdx(562354, 3).
In the first step, modDivisor becomes 10^4, which equals 10000.
In the second step, remainder is set to 562354 % 10000, which equals 2354.
In the third and final step, digit is set to remainder / (10000 / 10). Breaking that down, we get remainder / 1000, which (using integer division) is equal to 2.
Our final step is return the digit we have acquired.
EDIT: As for the sort logic itself, you may want to look here for a good idea.
The general process is to compare the two digits, and if they are equal move on to their next digit. If they are not equal, put them in the bucket and move on.

java assigning values to an array

so i'm creating a program in java where you enter scores and it classifies them into deciles (0-9, 10-19, 20-29, ... 80-89, 90-100) and I've got a grasp on how the program is supposed to work but I'm missing one key element. I create an array with 10 elements (one for each decile range). Once the user inputs their score it divides by 10 and then needs to put the score into it's appropriate spot in the array, but that's where I'm lost. It has to do a bunch of things after that, that I understand but how am I supposed to tell the code when someone enters 55 to increase the 50-59 part of the array by 1 and so on?
Um, it sounds like you just want:
bucketedScores[score / 10]++;
Don't you? Or possibly clearer:
bucketedScores[score / 10] = roughScores[score / 10] + 1;
int index = value / 10;
myArray[index] += 1;
FYI, given what you said, you will get an IndexOutOfBoundsException with a score of 100. May need to deal with that.
Try it this way....
bucketedScores[score / 10] = roughScores[score / 10] + 1;
Sounds like
int[] myarray = new int[10];
// Divide and increase the number returned (like 84/10 = 8 in integer division)
myarray[num/10]++
Though 100 would throw it off, you would need a special case for that one.
According to the Question
get into loops say for example i hope you're dividing 100 values 10-10 each. Use for loops and check and categorize it by assigning the input to a temporary variable for each iteration of inputs.
for(int i=0; i<=100; i++)
{
if(a[i] >= 0 && a[i] < 10)
your desired o/p(execution)
else if(a[i] > 10 && a[i] < 20)
your desired o/p(execution)
}
As the range is has 101 values from 0 to 101 you need to do more than divide by 10.
Do you mean like?
int[] scores = new int[10];
int decile = ...
int score = ....
scores[Math.min(9, decile/10)] += score;
This ensures that 100 is mapped to 9. Another solutions is to use (int)(decile/10.1) which would maps 0 to 10 to the first decile.

How to combine two FORs into one

This might be stupid, but I'm want to know if it's possible, lets start with 5x5 a matrix
int[][] x = new int[5][5];
Random rg = new Random();
now let's fill it with Pseudo Random information
for(int i=0;i<5;i++){
for(int j =0; j<5;j++){
x[i][j] = rg.nextInt();
}
}
but how can I do this right with one Single for?
for(int i=0, j=0; i<5; (j==5?i++, j=0:j++){
x[i][j] = rg.nextInt();
}
this is not working :(
You need to compute the row and column from a single index, then:
for(int i = 0; i < 5 * 5; i++)
{
int row = i / 5;
int column = i % 5;
x[row][column] = rg.nextInt();
}
The use of / and % is classic, here: as you iterate over the indices of the matrix, the division is used to figure out which row you're on. The remainder (%) is then the column.
This gorgeous ASCII art shows how the 1-dimensional indices are located in the 2D matrix:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
It should be clear that for any value in the first row, that value divided by 5 is the row index itself, i.e. they're all 0.
You really will not gain anything from doing that. keep your code readable. it's actually more intensive to do the multiplications and divisions unwind suggested then to just to a loop. (multiply divide and mod are actually a complex set of instructions in an ALU)
Another way to do it would be:
int i,j;
for (i=0,j=0; i<5 && j<5; i = (i==4 ? 0 : i+1), j = (i==4 ? j+1 : j))
{
x[i][j] = rg.nextInt();
}
Although, I prefer unwind's solution.
I got curious and did a benchmark.
For Suns HotSpot 64 server jvm on Linux, both nested loops and unwrapped loops were more or less equally fast, and almost as fast as iterating over a linear array of [size*size]. The unwrapped loop where infact slowe than the nested loop, probably because it does some more math.
However, On IBMs jdk 1.5 32 bit on Windows, the nested loop is more than 10x slower.
Though, I am not sure if its the compiler or the jvm that matters in this case, the slower test was compiled using IBMs RAD wich is some year older than eclipse 3.4
So the only reason to mess up your code with these optimizations would be if you are stuck on an "enterprisy" platform with an old jvm and and compiler, and it's really really time critical.
the nested loops will be extremely fast once the hotspot compiler runs them a few times..
see this excellent article for an explanation.
Shortest solution
int i = 0,j=0;
for(;j<5;j+=i==4?1:0,i++){
if(i==5)
i=0;
x[j][i] = rg.nextInt();
}
int q = 5, r= 5;
int [][] x = new int [q][r]
for(int i = 0; i < q * r; i++)
{
int xaxis = i / q;
int yaxis = i / r;
x[xaxis][yaxis] = rg.nextInt();
}
Though I don't know why you'd want to... you still have the same number of iterations
and this is IMHO more difficult to read and requires more mathematical calculations to run, so it's probably slower if you profile it

Categories