Different results in Java and Python when computing powers - java

I am trying to teach myself Java by working through the problems on projecteuler.net, as I have done previously with Python. When attempting problem 16, I replicated the method I used previously in Python. However the result output was different in the two languages. I think it is something to do with Java data types being different from Python. The problem is to sum the digits in the number 2^1000.
In Python:
def sumdigits(n):
s = 0
while n > 0:
s = s + (n % 10)
n = n / 10
return s
print sumdigits(pow(2,1000))
In Java:
public static double SumDigits(double n){
double s = 0;
while (n > 0){
s = s + (n % 10);
n = n / 10;}
return s;
}
System.out.println(SumDigits(Math.pow(2,1000)));
Python produced the correct result and Java produced 1197.1463275484991
Why would these be different?

In Java, double cannot accurately represent 2^1000. As a floating-point number, Math.pow(2,1000) is 1.0715086071862673E301.
To get the result that you want, use BigInteger which preserves the actual value of 2^1000.
public static BigInteger sumDigits(BigInteger n) {
BigInteger num = n;
BigInteger sum = BigInteger.ZERO;
BigInteger ten = BigInteger.valueOf(10);
while (num.compareTo(BigInteger.ZERO) > 0) {
sum = sum.add(num.mod(ten));
num = num.divide(ten);
}
return sum;
}
public static void main(String[] args) {
System.out.println(sumDigits(BigInteger.valueOf(2).pow(1000)));
}
The output of the above code is 1366.

The basic number types in Java are int and double. Both cannot handle a number with 1000 bits. Python has a arbitrary large integer type builtin. For Java you have to find another solution.
In languages with arbitrary large integer arithmetics this problem is trivial
print sum(int(x) for x in str(2**1000))
If you don't have this tool, you have to code multiplication by two on your own.

Related

For two given positive numbers a and b. Find a raised to b. Output your number modulus 10^9+7

https://practice.geeksforgeeks.org/problems/abset-2/0/ , this is a gfg question where i am asked to output my number (a ^ b) modulus 10^9+7.
so here is my first code;
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while(t--!=0){
int a = sc.nextInt();
int b = sc.nextInt();
int result = 1;
for(int i = 0; i<b; i++){
result = result*a;
}
System.out.println(result%1000000007);
}
}
and it is not giving the correct output for 99^928. Then i changed the data type of result into long even that's giving a negative number. Then i had to change my code like this and it worked
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while(t--!=0){
int a = sc.nextInt();
int b = sc.nextInt();
long result = 1;
for(int i = 0; i<b; i++){
result = (result*a);
result = result%1000000007;
}
System.out.println(result);
}
here my question is when i put the result%1000000007 in the for loop how it worked, according to the problem was not i supposed to output the ultimate result modulus 10^9+7?
int and long have maximum values. Depending on a and b a^b exceeds that maximum and overflows.
The modulo operation in the end would then act on the wrong overflow value and the result would be off.
The thing with modulo is that you can apply modulo during your computation basically whenever you want without changing the result. (a + b) mod m has the same value as (a mod m + b mod m) mod m and similarly (a * b) mod m is the same as (a mod m * b mod m) mod m, that is simply how the modulo operator works. Simply play around with a few small values of a b and m on paper to see that the rules work.
It is very typical for assignments involving HUGE values to be computable only if you add some mod m steps somewhere in the mix (as long as they make sense).
99^928 is a large number with 1852 digits. The primitive data types int and long in Java don't have the storage capacity for such a number: the largest value you can store in an int is 2147483647 and the largest you can store in a long is 9223372036854775807. Operations that return larger values wrap around, returning a value that is correct modulo a power of 2, but completely unusable for most practical purposes.
If you printed out the intermediate values, you would see the result wrap around already at 99^10:
99^9 = 913517247483640899
99^10 = -1795512867667309079
This means if you wait to do the modulo operation until the last moment, you will be taking the modulo of an incorrect intermediate result. You must control how large the values get by using modulo already in the intermediate steps.
Note that Java does have classes for dealing with integers bigger than fits in a long: java.math.BigInteger. It even has a convenient and fast method for the "modular power" operation you are implementing:
BigInteger base = BigInteger.valueOf(1000000007);
BigInteger result = BigInteger.valueOf(a).modPow(BigInteger.valueOf(b), base);

I wrote this program to find if a given input is power of 2 , this program is not running for very large number such as 10^18 or so. what should i do

This is a program to check if an input is power of 2 or not. This program is running fine for inputs up to 8 digits but when I am giving input like 1018, it is not working, What should I do?
import java.util.Scanner;
public class search {
public static void main(String [] args){
//to take how many inputs are there
Scanner sc = new Scanner(System.in);
int k ;
k = sc.nextInt();
for(int i = 0 ;i<k;i++){
// input number n
long n ;
n = sc.nextInt();
if ((n > 0) && ((n & (n - 1)) == 0)){
System.out.println("YES");
}
else{
System.out.println("NO");
}
}
}
}
The problem is that 1018 is out of range of Java int, which stores numbers up to 231-1, or roughly 2*109. You can expand the range of your program by using long in place of int to accept numbers up to 9*1018, or to make it accept virtually unlimited range by using BigInteger:
BigInteger n = new BigInteger(numericString);
BigInteger test = n.and(n.subtract(BigInteger.ONE));
if (test.equals(BigInteger.ZERO)) {
...
}
You need to get your input number as String then use BigInteger class to avoid limit surpassing problem,
BigInteger inputNumber = new BigInteger(inputString);
Also, refer What does BigInteger having no limit mean? to know more about BigInteger limits.
If the long number range is enough, you can just change
n = sc.nextInt();
to
n = sc.nextLong();
At the moment, n is only set to an integer and therefore limited to the int number range.
Better Use Class BigInteger it implement Serializable, Comparable<BigInteger> .BigInteger provides operations for modular arithmetic, GCD calculation, primality testing, prime generation, bit manipulation, and a few other miscellaneous operations.
input="Number"
BigInteger number = new BigInteger(input);
//Do your stuff
Happy to help thanks
Take the input in long:
k = sc.nextLong();

How to calculate and display large numbers in java

How could I calculate and display all digits of large numbers like 9999! (factorial of 9999) in java?
Take a look at this url which calculates 9999! and dislays all digits.
Use BigInteger, his limit is your memory
public static BigInteger factorial(BigInteger num) {
if (num.compareTo(new BigInteger("1")) < 0) {
return new BigInteger("1");
} else {
return factorial(num.subtract(new BigInteger("1"))).multiply(num) ;
}
}
Use BigInteger; 9999! took 120 ms with Java 8. Here is a version that uses longs, and halves that time:
public static BigInteger factorial(int n) {
// Try first to use longs in calculating the factorial.
BigInteger result = BigInteger.ONE;
long factor = 1;
for (int i = n; i > 1; --i) {
if Long.MAX_VALUE / factor < i) { // Overflow?
result = result.multiply(BigInteger.valueOf(factor));
factor = i;
} else {
factor *= i;
}
}
return result.multiply(BigInteger.valueOf(factor));
}
The Java standard library provide a BigInteger class, which can represent unlimited integer values (actually, they are limited, but only by available memory).
Not the fastest, but not really slow either.
public static BigInteger factorial(int n) {
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= n; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
You can use Strings (yes don't get astonished, you can!). A program can be created in strings to multiply two very large numbers (here i am talking about numbers say 5000 digits in length, each!)
I have already created them for addition and subtraction and it's not that hard to create it for Multiplication and i assure you that, though you will think that using BigInteger will be faster, but using Strings would be Ultrafast as compared to BigInt.
And the thing that slipped my mid, i used StringBuilder class to make the program more efficient.

Java: avoiding factorial overflow

I'm supposed to optimize the following code so that it calculates the central binomial coefficient up to the max value of integer (up to n = 16).
public static int factorial(int n)
{
int result= 1;
for(int i = 2; i <= n; i++) result *= i;
return result;
}
public static int centralbinom(int n)
{
return factorial(2*n) / (factorial(n) * factorial(n));
}
Naturally I get an overflow for every n > 6.
How do I 'break down' the factorial function so that doesn't has to deal with big numbers such as 2n = 2*16 = 32 ?
Or is there a better way to calculate the central binomial coefficient?
Here are several optimizations that you can do in addition to using BigIntegers that may reduce your calculations, in most of you cases overflow that you may be having in your program.
Since you need factorial(n) at least two time. Calculate it once and store it in a variable.
Factorial(2*n) has factorial(n) in it. Since you have already calculated factorial(n) before all you need to do is calculate till factorial(2n....n) and then multiply factorial(n) to it. Here's one way how that can be done.
//Pseudocode
//find factorial of n given I know already till k
int findFactorial(n, k) {
int result = 1
for i n to 1
if(i==k)
break;
result = result * n;
return result
}
//factorial(2*n) = facorial(n, k) * factorial(k)
This will reduce your calculations a lot and in case if you expect your program not to have an overflow, you can go away with BigIntegers.
If you need a factorial of big number, you have to use BigInteger class to calculate result:
public static BigInteger factorial(int n) {
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= n; ++i) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
If the central binomial coefficient of 17 is greater than the integer max, and you only need to compute it for 17 numbers, then the obvious solution is a lookup table. Create a 17-element array containing the central binomial coefficient for n = 0 to 16. I think you'll find this solution is extremely efficient.
You can find a list of them here. http://oeis.org/A000984
Just compress your factorial by gamma.
set gamma to 10 is good enough
public static double factorial(int n, double gamma)
{
double result= 1;
double gammaInv = 1.0/gamma;
for(int i = 2; i <= n; i++) result *= pow(i,gammaInv);
return result;
}
public static int centralbinom(int n, double gamma)
{
return pow(factorial(2*n,gamma) /
(factorial(n,gamma) * factorial(n),gamma),
gamma);
}

Why java.Math.BigInteger bugs out after a certain limit?

Am trying to print the sum of digits in 2^n for n = 1 to 1000.
Here's what I've done.
public static void main(String[] args) {
int n = 1000;
for (int i = 1; i < n; i++) {
BigInteger power = BigInteger.valueOf((int)Math.pow(2, i));
int sum = 0;
while (power.intValue() > 0) {
sum += power.intValue() % 10;
power = power.divide(BigInteger.valueOf(10));
}
System.out.print(sum + " ");
}
}
It works only till about 2^30 or so and then prints the same result, 46, for the rest.
I tried a similar thing using "long long" in C and that printed 0's after a similar limit.
According to the answers, I changed
BigInteger power = BigInteger.valueOf((int)Math.pow(2, i));
to
BigInteger power = BigInteger.valueOf(2).pow(i);
and 46 changed to 0. Just like C.
Still not working...
You're using Math.pow to generate the value you should use the BigInteger functions to do so instead.
The sum should be stored in a BigInteger as well not an int.
You are doing integer arithmetic and then putting it into a biginteger. Use a biginteger's pow method instead.
Because you aren't using BigInteger.
Computing numbers using BigInteger doesn't let you magically store their sum in an int.
Similarly, passing an int to BigInteger.valueOf() doesn't magically make that int bigger.
You're calling Math.pow() with regular integers, not BigIntegers. You're calling it on integer literals.
You want this:
int i = 7; //or whatever power
BigInteger k = BigInteger.valueOf(2);
k = k.pow(i);

Categories

Resources