Issue with large number [duplicate] - java

This question already has answers here:
Counting trailing zeros of numbers resulted from factorial
(10 answers)
Closed 2 years ago.
I'm trying to count the number of trailing zero with a factorial.
e.g
4! = 24 So you retrieve 0.
9! = 362880 So you retrieve 1.
10! = 9! x 10 = 3628800 So you retrieve 2.
11! = 10! x 11 = 3.99168E7 So you retrieve 2.
static double factorial(double n) {
double f = 1;
for(int i = 1 ; i <= n ; i++) {
f *= i;
}
return f;
}
static int numberOfZeros(double f) {
int ten = 1;
int count = 0;
for(;f%Math.pow(10, ten) == 0;count++) {
ten++;
}
return count;
}
this codes are Okay until number n is 22. but when i try to put 23 into then count is 0.
Of course, mathematically 23! has trailing zeros.

You don't need to calculate the factorial to count trailing zeroes.
Just see how many times you can divide by powers of 5 (which is the larger factor of 10). This works since any number with a trailing zero will be divisible by 10. You need to do the powers of 5 to catch those times when 5 occurs more than once.
for 45! = 45/25 = 1 + 45/5 = 9 = 10 zeroes.
for 150! = 150/125 = 1 150/25 = 6, 150/5 = 30 so 1 + 6 + 30 = 37 zeros.
Now all you have to do is code it.

The reason your code isn't working is that a double type can only hold 64 bits. Let's do the calculation:
A bit has two possible values, so 2^64 is the largest number a double could hold... if we aren't accounting for negative numbers. Of course, Java doubles support negative values, so we divide 2^64 (18,446,744,073,709,551,616) by two, and then subtract 1 (Because Java takes one number from the positive range to store zero). As a result, we get 9,223,372,036,854,775,807, which represents the positive bound for the Java double type, or in other words, the biggest positive number a double can store.
Now, 23 factorial is a very big number:
25,852,016,738,884,976,640,000
9,223,372,036,854,775,807
Above is the range for a double. Just by looking at the widths of the numbers, we can see that 23! exceeds the range for a double. Therefore, your double value will overflow and you won't get the right answer.
You should consider using the BigInteger class to handle such large numbers and ensure you are getting accurate answers.
GeeksForGeeks BigInteger tutorial
Java API documentation for BigInteger

Related

calculate Check Number in Java

Not sure if anyone can explain this to me or help me.
I have a 15 Digit Number of which I want to multiply each even number by 2 unless the even number is greater than 9. If it is this needs to be subtracted by 9 to give me an integer that again I can multiply by 2. Once I have all the even numbers multiplied by 2 i need to add them all together with the odd numbers.
Does that make sense.
UPDATE ***
so i have a number say 49209999856459. for that number I am looking to get the even integer so for example the first even one would be 4 then the second would be 2 and so on.
If one of those even numbers are multiplied by 2 then it might be above 9 so I want to subtract 9 to then use the remainder as the even number in its place.
SO !!!
Multiply by 2 the value of each even digit starting from index 0 and then each even index. In each case, if the resulting value is greater than 9, subtract 9 from it (which reduces larger values to a single digit). Leave the values of the digits at the odd indexes unchanged.
public String calculateCheckNumber()
String firstFifteen = longNumber.substring(0,15) ;
int i, checkSum = 0, totalSum = 0;
for (i = 0; i<firstFifteen.length(); i += 2) {
while (i < 9)
i *= 2;
if (i > 9)
i -= 9 ;
}
Was one option I was trying but it honestly I cant seem to get my head around it.
Any Help would be greatly appreciated.
Well, here is one approach. This uses the ternary (?:) operator to condense the operations. Edited base on clarification from the OP. The example you gave is actually a 14 digit string. But the following will work with any number of digits if they start out in a string. If you have a long value, then you can create the character array using:
long v = 49209999856459L;
char[] d = Long.toString(v).toCharArray();
Here is the main algorithm.
String s = "49209999856459";
int sum = 0;
char[] d = s.toCharArray();
for (int i = 0; i < d.length; i++) {
int v = d[i] - '0';
// The even digit will only be greater than 9 after
// doubling if it is >= 5 before.
sum += ((i % 2) == 1) ? v : (v >= 5) ? v+v-9 : v+v;
}
System.out.println(sum);
Prints
86

Improve performance of string to binary number conversion

This is one of the questions that I faced in competitive programming.
Ques) You have an input String which is in binary format 11100 and you need to count number of steps in which number will be zero. If number is odd -> subtract it by 1, if even -> divide it by 2.
For example
28 -> 28/2
14 -> 14/2
7 -> 7-1
6 -> 6/2
3 -> 3-1
2 -> 2/2
1-> 1-1
0 -> STOP
Number of steps =7
I came up with the following solutions
public int solution(String S) {
// write your code in Java SE 8
String parsableString = cleanString(S);
int integer = Integer.parseInt(S, 2);
return stepCounter(integer);
}
private static String cleanString(String S){
int i = 0;
while (i < S.length() && S.charAt(i) == '0')
i++;
StringBuffer sb = new StringBuffer(S);
sb.replace(0,i,"");
return sb.toString();
}
private static int stepCounter(int integer) {
int counter = 0;
while (integer > 0) {
if (integer == 0)
break;
else {
counter++;
if (integer % 2 == 0)
integer = integer / 2;
else
integer--;
}
}
return counter;
}
The solution to this question looks quite simple and straightforward, however the performance evaluation of this code got me a big ZERO. My initial impressions were that converting the string to int was a bottleneck but failed to find a better solution for this. Can anybody please point out to me the bottlenecks of this code and where it can be significantly improved ?
If a binary number is odd, the last (least significant) digit must be 1, so subtracting 1 is just changing the last digit from 1 to 0 (which, importantly, makes the number even).
If a binary number is even, the last digit must be 0, and dividing by zero can be accomplished by simply removing that last 0 entirely. (Just like in base ten, the number 10 can be divided by ten by taking away the last 0, leaving 1.)
So the number of steps is two steps for every 1 digit, and one step for every 0 digit -- minus 1, because when you get to the last 0, you don't divide by 2 any more, you just stop.
Here's a simple JavaScript (instead of Java) solution:
let n = '11100';
n.length + n.replace(/0/g, '').length - 1;
With just a little more work, this can deal with leading zeros '0011100' properly too, if that were needed.
Number of times you need to subtract is the number of one bits which is Integer.bitCount(). Number of times you need to divide is the position of most-significant bit which is Integer.SIZE (32, total number of bits in integer) minus Integer.numberOfLeadingZeros() minus one (you don't need to divide 1). For zero input I assume, the result should be zero. So we have
int numberOfOperations = integer == 0 ? 0 : Integer.bitCount(integer) +
Integer.SIZE - Integer.numberOfLeadingZeros(integer) - 1;
As per the given condition, we are dividing the number by 2 if it is even which is equivalent to remove the LSB, again if number is odd we are subtracting 1 and making it an even which is equivalent to unset the set bit (changing 1 to 0). Analyzing the above process we can say that the total number of steps required will be the sum of (number of bits i.e. (log2(n) +1)) and number of set bits - 1(last 0 need not to be removed).
C++ code:
result = __builtin_popcount(n) + log2(n) + 1 - 1;
result = __builtin_popcount(n) + log2(n);

Is there better way of iteration to find the evenly divisible number?

I'm trying to solve this problem:
"2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"
Please, do not tell me the answer, I really want to solve it by myself. All I need is an advice regarding math aspect of the question. The thing is adding one every cycle isn't a good idea because the process is too slow. Or is there a problem with variable type not being long?
I've tried to get number which is evenly divisible of all numbers between (1 and 10), and even (1 and 17), and the algorithm worked well.
int in_num = 1;
int score = 0;
public void calculate() {
while (true) {
score = 0;
for (int x = 1; x < 21; x++) {
if ((in_num%x) == 0) {
score++;
}
}
System.out.println("Number " + in_num + " has " + score );
if (score == 20) {
System.out.println(in_num);
break;
}
in_num++;
}
I expect the specific integer, but I get infinite loop.
Isn't this enough?
Multiply every prime number from 1 to 20 to get the number! Also instead of 2 use 16 and instead of 3 use 9.
Long number = 2 ^ 4 * 3 ^ 2 * 5 * 7 * 11 * 13 * 17 * 19L;
System.out.println(number);
Detailed Answer:
We need to find every prime number less than 20. After that, for each prime number, we must calculate the number to which we can exponentiate the prime number while it stays less than 20.
For example, if we multiply 2 four times with itself it remains below 20 (16). But if we calculate 2 to the fifth, it will be 32 which is greater than 20.
We will do the same for every other prime number. By this calculation the actual answer will be like this:
Long number = 2 ^ 4 * 3 ^ 2 * 5 ^ 1 * 7 ^ 1 * 11 ^ 1 * 13 ^ 1 * 17 ^ 1 * 19L ^ 1;
The lowest common multiple of two numbers x and y is xy/GCD(x,y), where GCD calculates the greatest common divisor.
You can implement GCD easily using Euclid's algorithm or the binary GCD algorithm: https://en.wikipedia.org/wiki/Greatest_common_divisor
The algorithm would be like:
result = 1;
for (x = 20; x > 0; --x)
result *= (x/GCD(x,result));
Of course this works for other numbers as well. If you really don't care about that, then you can just print 232792560
You are getting an infinite loop because of int (in_num) range exceeded its length; replace type int to Long (something bigger than int) you will not get any infinite loop and you will get your output.

Adding all numbers from 1 to N which have number of set bits as 2

I have a question where I have to add numbers from 1 to N which have their set bits as 2. Like for N = 5 we should get value 8, as number 3 and 5 have 2 bits set to one. I am implementing the same in java. I am getting the o/p correct for int value but when it comes to the long values, either it's taking a lot of time or freezing, and when I submit the same on code judge sites, it's giving run time exceeded message. Please guide me how may I optimise my code to run it faster, thanks :)
public static void main(String[] args)
{
long n = 1000000L;
long sum = 0;
long start = System.currentTimeMillis();
for(long i = 1L ; i <= n ; i++)
{
if(Long.bitCount(i) == 2)
{
sum += i;
}
}
long end = System.currentTimeMillis();
System.out.println(sum);
System.out.println("time="+(end-start));
}
As #hbejgel notes, there is no point in looping over all numbers and checking their bit count. You can simply construct numbers with 2 bits and add them up.
You can construct a number with 2 bits by picking two different bit positions in the long, the "higher" bit and the "lower" bit":
long i = (1 << higher) + (1 << lower);
So, you can simply loop over all such numbers, until the value you have constructed exceeds your limit:
long sum = 0;
outer: for (int higher = 1; higher < 63; ++higher) {
for (int lower = 0; lower < higher; ++lower) {
long i = (1 << higher) + (1 << lower);
if (i <= n) {
sum += i;
}
if (i >= n) break outer;
}
}
Let's say we know the closest number, x, equal to or lower than N with 2 set bits, then we can use the formula for power series to quickly sum all positions of the two set bits, for example, if x = b11000, we sum
4*2^0 + S(4)
+ 3*2^1 + S(4) - S(1)
+ 2*2^2 + S(4) - S(2)
+ x
where S(n) = 2 * (1 - 2^n) / (1 - 2) 
= 2 + 2^2 + 2^3 ... + 2^n
With numbers encoded 2 out of 5, exactly two bits are set in every one-digit number. The sum is 45, with the exception of N×(N-1)/2 for 0≤N<9.
I think the question is supposed to discover the pattern.
Fast forward. Given a number N, you can tell the largest number
should count by bitmask from the first two bits are set. So you have
a smaller number M
Skip to next counted number Given any number with two bit set, next
largest number is the shift the second bit by one, until underflow.
Skip to next order When underflow happens on set two, shift the
highest bit by one and also the bit on it's right.
You don't really need a loop on N, but the bits it have.
Next question: can you answer a large number? which N >100,000,000
Next Next question: can you answer the same question for X bits when X>2

Can't understand logic of code to find the sum of the evenly positioned digits

So basically the question is something like:
Write a program to accept a number from the user and find the sum of the evenly positioned digits counting from the left. For eg. if input is 94852 then output is 9(4+5).
Now, I am aware that this question can be done by converting the number to a string and using arrays, but in fact there is a better way of doing it.
The following program demonstrates the method -:
public class Question {
public static void main(int a) {
int evenSum = 0, oddSum = 0;
int b = a; //b is used as a's value eventually becomes 0.
while(a>0) {
int sum = evenSum + a % 10;
evenSum = oddSum; //Switching sums(?)
oddSum = sum; //Interestingly,oddSum stores the sum of the oddly positioed digits
a = a / 10;
}
System.out.println("The number entered is "+b);
System.out.println("The even sum is " + evenSum);
}
}
I happened to come across this answer when I was scouting for alternate solutions, and it left me stunned. I just couldn't understand the logic.
So can someone please explain what this method does and why it works?
Its a combination of maths & programming. I added a print statement after evenSum & this is the output what i got:
94852= a, 2 = a%10, 0 = evenSum,2 = sum in Step 1
9485= a, 5 = a%10, 2 = evenSum,5 = sum in Step 2
948= a, 8 = a%10, 5 = evenSum,10 = sum in Step 3
94= a, 4 = a%10, 10 = evenSum,9 = sum in Step 4
9= a, 9 = a%10, 9 = evenSum,19 = sum in Step 5
The number entered is 94852
The even sum is 9
2 rules are involved here:
1. Dividing a number by 10 leaves a decimal which gets omitted if variable declared as int.
2. Dividing a number by 10 leaves the remainder as the last digit if variable declared as int.
Rest all is self explanatory !
The code repeatedly shifts a digit to the right (integer division by 10). It picks the right most digit by modulo 10 (remainder of integer division).
It alternatively in the loop in one step sums in the one sum variable, in the next step in the other sum variable.
So one has two sums: of "odd" and "even" digits.
However as you name "odd" and "even" for positions from the left, and the loop starts from the right, you cannot say at the first step, first digit, wether that digit is at an odd or even position (counting from the left).
Hence you need to sum both odd and even positions.
And by swapping odd and even sums in every step, you ensure that always the momently last digit is added to the oddSum, evenSum indeed is the "even" sum.
The code works because we use a decimal number system, in other words, each position in a number is 10 times as big as one to the right.
a%10 is is taking the remainder of dividing by 10, and since all the numbers in all the positions other than the ones digit are divisible by 10, all you are left with is the ones digit.
a = a/10 on the other hand is doing integer division (divide and drop the remainder) of the number meaning that you drop the ones digit of the number off of the end.
evenSum and oddSum The two sums are alternated so that the previous loop itterations sum is always stored in even sum and this iterations sum in oddSum. We know that the last iteration when the code completes is going to be on the left most digit (the first digit in your problem definition) and so is going to be the odd sum.
This is the basic code to extract each digit of the number
while (a > 0) {
int digit = a % 10;
a /= 10;
}
The trick is to add each digit alternately to the even or odd sum
a = 0; b = 0; // these represent evenSum and oddSum
repeat
take the last digit
add the digit to b
swap a and b // alternates
remove the last digit
Adding the digit to b is done with a temporary variable 'sum'

Categories

Resources