Divisor value in for loop is mysteriously (?) changing - java

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.

Related

How to convert decimal to binary in java

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:

Java while loop printing squared numbers can't use int?

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

Bulls and Cows Java code explanation

I've been searching for the source code of this game and found this one. However, I didn't understand the hasDupes method at the end of the code.
Could you explain it to me?
Source code - here
public static boolean hasDupes(int num){
boolean[] digs = new boolean[10];
while(num > 0){
if(digs[num%10]) return true;
digs[num%10] = true;
num/= 10;
}
return false;
So let's step through it:
boolean[] digs = new boolean[10];
In Java, all the items in an array declaration are given a default value. In the case of boolean, it is false. So this creates an array of 10 elements where each element is false
while(num > 0){
if(digs[num%10]) return true;
digs[num%10] = true;
num/= 10;
}
Modding a number by 10 (num % 10) and then dividing by 10 (num/= 10) is a common way to "pop" off the last digit from a number. For example,
int someNum = "1357";
int lastDigit = mod % 10; // lastDigit is 7
someNum /= 10; // someNum is now 135
As you can see, the 7 gets removed. So the while loop is just popping of each digit of num until all the digits are processed. Now, for each digit that is being removed, digs[num%10] = true; is simply keeping track of the digits already removed. By keeping track of these, if(digs[num%10]) return true; will return true from the method if a digit has already been processed.
So, in much simpler words, this method just checks to see if a number contains more than 1 of the same digit.
12345 will return false
12341 will return true
Just make a pen & paper test. Our number system has 10 digits: 0 to 9. digs represents, whether a digit has occured already. with num % 10 you get the last digit of num. So let's say num has an 1 at the least significant position. That means: digs[i] will be set to true (digs[num%10] = true;). Now let's look on: with num /= 10 you remove the last digit from an integer. For example, 3211 /= 10 will be 321 (integer arithmetics, I know you cannot apply /= to literals, but it is only a demonstration to explain the semantics). Since num is > 0, the loop is executed again. This time, the if-condition will be true (because we set digs[1] to true one iteration before), we found a duplicate digit. If the method is able to leave the loop without entering the if, num has pairwise unequal digits. That's it.
It's checking if any value in base 10 has duplicated digits.
So 9019 has duplicated digits (9) when written as a decimal value. 123 does not.
In the context of the game, it basically checks to see if the given integer, num, has duplicated digits. It does so by creating an array of 10 boolean values, such that two digits that are duplicated will be dropped into the same cell in the array. The algorithm uses
An array of 10 boolean values to represent each digit in our base 10 number system. So if you are dealing with base 16 number system, you will need an array of 16 boolean values.
num modulo 10 to extract the least significant digit of num until all digits have been examined. Again, it uses modulo 10 because it is assuming a base 10 number system.
The moment that duplicated digits are detected, the method returns true:
if(digs[num%10]) return true;
If you look at the main() method in your sample codes, the algorithm will attempt to keep generating random number, until one with no duplicated digits is found.
while(hasDupes(target= (gen.nextInt(9000) + 1000)));

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.

Issue with implementation of Fermat's little therorm

Here's my implementation of Fermat's little theorem. Does anyone know why it's not working?
Here are the rules I'm following:
Let n be the number to test for primality.
Pick any integer a between 2 and n-1.
compute a^n mod n.
check whether a^n = a mod n.
myCode:
int low = 2;
int high = n -1;
Random rand = new Random();
//Pick any integer a between 2 and n-1.
Double a = (double) (rand.nextInt(high-low) + low);
//compute:a^n = a mod n
Double val = Math.pow(a,n) % n;
//check whether a^n = a mod n
if(a.equals(val)){
return "True";
}else{
return "False";
}
This is a list of primes less than 100000. Whenever I input in any of these numbers, instead of getting 'true', I get 'false'.
The First 100,008 Primes
This is the reason why I believe the code isn't working.
In java, a double only has a limited precision of about 15 to 17 digits. This means that while you can compute the value of Math.pow(a,n), for very large numbers, you have no guarantee you'll get an exact result once the value has more than 15 digits.
With large values of a or n, your computation will exceed that limit. For example
Math.pow(3, 67) will have a value of 9.270946314789783e31 which means that any digit after the last 3 is lost. For this reason, after applying the modulo operation, you have no guarantee to get the right result (example).
This means that your code does not actually test what you think it does. This is inherent to the way floating point numbers work and you must change the way you hold your values to solve this problem. You could use long but then you would have problems with overflows (a long cannot hold a value greater than 2^64 - 1 so again, in the case of 3^67 you'd have another problem.
One solution is to use a class designed to hold arbitrary large numbers such as BigInteger which is part of the Java SE API.
As the others have noted, taking the power will quickly overflow. For example, if you are picking a number n to test for primality as small as say, 30, and the random number a is 20, 20^30 = about 10^39 which is something >> 2^90. (I took the ln of 10^39).
You want to use BigInteger, which even has the exact method you want:
public BigInteger modPow(BigInteger exponent, BigInteger m)
"Returns a BigInteger whose value is (this^exponent mod m)"
Also, I don't think that testing a single random number between 2 and n-1 will "prove" anything. You have to loop through all the integers between 2 and n-1.
#evthim Even if you have used the modPow function of the BigInteger class, you cannot get all the prime numbers in the range you selected correctly. To clarify the issue further, you will get all the prime numbers in the range, but some numbers you have are not prime. If you rearrange this code using the BigInteger class. When you try all 64-bit numbers, some non-prime numbers will also write. These numbers are as follows;
341, 561, 645, 1105, 1387, 1729, 1905, 2047, 2465, 2701, 2821, 3277, 4033, 4369, 4371, 4681, 5461, 6601, 7957, 8321, 8481, 8911, 10261, 10585, 11305, 12801, 13741, 13747, 13981, 14491, 15709, 15841, 16705, 18705, 18721, 19951, 23001, 23377, 25761, 29341, ...
https://oeis.org/a001567
161038, 215326, 2568226, 3020626, 7866046, 9115426, 49699666, 143742226, 161292286, 196116194, 209665666, 213388066, 293974066, 336408382, 376366, 666, 566, 566, 666 2001038066, 2138882626, 2952654706, 3220041826, ...
https://oeis.org/a006935
As a solution, make sure that the number you tested is not in this list by getting a list of these numbers from the link below.
http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
The solution for C # is as follows.
public static bool IsPrime(ulong number)
{
return number == 2
? true
: (BigInterger.ModPow(2, number, number) == 2
? (number & 1 != 0 && BinarySearchInA001567(number) == false)
: false)
}
public static bool BinarySearchInA001567(ulong number)
{
// Is number in list?
// todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
// Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
}

Categories