I am trying to find the sum of the digits of the number 2^1000 and I am using Java BigInteger class for this. However, I could not make it real. Eventually, I get a 0 (zero) with the following code. What might be the problem?
Thanks...
After Kon's help I fixed the problem, but this time I get a wrong result. Can anyone see the problem with the algorithm?
public static void main(String []args) throws Exception
{
BigInteger big = BigInteger.valueOf(2).pow(1000);
BigInteger big2 = BigInteger.valueOf(0);
//System.out.println(big);
for(long i = 1; i<283; i++)
{
big2 = big2.add(big.mod(BigInteger.valueOf((long) Math.pow(10,i))).divide(BigInteger.valueOf((long)Math.pow(10,i-1))));
}
System.out.println(big2);
}
Trying to calculate each digit of BigInteger using mod is not very efficient, because of many method calls you are doing in the process. Instead you can simplify by doing the conversion to String and getting each digit straight away.
BigInteger big = BigInteger.valueOf(2).pow(1000);
String digits = big.toString();
int sum = 0;
for(int i = 0; i < digits.length(); i++) {
int digit = (int) (digits.charAt(i) - '0');
sum = sum + digit;
}
System.out.println(sum);
The BigInteger class is immutable, therefore you have to assign the result of the operation to the variable itself.
big2.add(big.mod(BigInteger.valueOf((long) Math.pow(10,i))).divide(BigInteger.valueOf((long)Math.pow(10,i-1))));
should become
big2 = big2.add(big.mod(BigInteger.valueOf((long) Math.pow(10,i))).divide(BigInteger.valueOf((long)Math.pow(10,i-1))));
For more on immutable objects in Java, please take a look at this documentation.
Also, although your question is not specifically about this, using hard coded literal values in your loops is very bad practice. You want to loop over each digit in the BigInteger 2^1000. Well, you could get the number of digits using something like big.toString().length().
Related
I'm trying to read a very large input as String and then converting it into long as per follows:[The program works for short input]
The input is two int separated by a space, example: "1248614876148768372675689568324619856329856295619253291561358926935829358293587932857923857934572895729511 413241"
My Code:
import java.io.*;
import java.math.*;
import java.util.*;
public class Solution {
public static void main(String args[] ) throws Exception {
Solution obj = new Solution();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
String input[]=new String[T];
for (int i=0;i<T;i++) {
input[i] = br.readLine();
}
for (int i=0;i<T;i++){
StringTokenizer st = new StringTokenizer(input[i]," ");
BigInteger N = new BigInteger(st.nextToken());
BigInteger P = new BigInteger(st.nextToken());
System.out.println(obj.result(N,P));
}
}
}
public BigInteger result(BigInteger N, BigInteger P){
BigInteger temp=1;
BigInteger c=0;
for (BigInteger i=0;i<=N;i++){
//System.out.println(nck(N,i));
if ((nck(N,i)%P) ==0)
c++;
}
return c;
}
public BigInteger nck(BigInteger N, BigInteger k){
if (k==0)
return 1;
else {
BigInteger temp=1;
BigInteger y=1;
BigInteger z=N;
while(k>=1){
temp=temp*z/y;
y++;
z--;
k--;
}
return temp;
}
}
}
I'm getting a java.lang.NumberFormatException
You can't parse this string into a long, it's too great (greater than Long.MAX_VALUE), you need BigInteger :
BigInteger bi = new BigInteger(st.nextToken());
Following your edit :
Don't try to iterate over a bigInteger : if it's too great to fit in a long, the loop will be too long for your time. Compare it with a reasonable limit and if it's smaller, then get it as int and enter your loop:
BigInteger MAX = new BigInteger("1000000");
if (bi.compareTo(MAX)<0) {
int N = bi.intValue();
for (int i=0; i<N; i++) {
Test...
}
}
If throws NumberFormatException because 248614876148768372675689568324619856329856295619253291561358926935829358293587932857923857934572895729511 is greater than Long.MAX_VALUE (which is 9223372036854775807).
As pointed out by others the valuse is too big for long However another problem is that there can be no spaces in the string which is being converted. There is a handy post on removeing white space from a string here
"The sequence of characters following an (optional) negative sign and/or radix specifier ("0x", "0X", "#", or leading zero) is parsed as by the Long.parseLong method with the indicated radix (10, 16, or 8). This sequence of characters must represent a positive value or a NumberFormatException will be thrown. The result is negated if first character of the specified String is the minus sign. No whitespace characters are permitted in the String." From the Docs
The value is too big for a long to hold. Primitive Data Types
I wonder what you are trying to do with so big integer but what you might be looking for is a BigInteger.
Immutable arbitrary-precision integers. All operations behave as if BigIntegers were represented in two's-complement notation (like Java's primitive integer types). BigInteger provides analogues to all of Java's primitive integer operators, and all relevant methods from java.lang.Math. Additionally, BigInteger provides operations for modular arithmetic, GCD calculation, primality testing, prime generation, bit manipulation, and a few other miscellaneous operations.
It provides methods for mathematical operations. Should also note that since it's immutable, any operation you perform on a BigInteger returns a new BigInteger.
Remember that when changing from type int to BigInteger you are then dealing with an object rather than a primitive. The BigInteger (String val) is probably the most useful constructor.
(i.e.) BigInteger temp = new BigInteger("1");
I am trying to compare numbers that are so large that even BigIntegers cannot deal with them. My solution is to convert the numbers to Strings and use String comparison on them.
Will this work? I am not really sure how to implement something like this. I am just attempting to unit test an algorithm to produce the factorial of 1000 for a project Euler program that I am sucked into.
Your assumption is wrong.
BigInteger provides arbitrary precision, so it can definitely deal with numbers this big.
Try the following:
public class Main {
public static void main(String[] args) {
BigInteger thousand = BigInteger.valueOf(1000L);
for (int i = 999; i > 0; i--)
{
thousand = thousand.multiply(BigInteger.valueOf(i));
}
System.out.println(thousand.toString());
}
}
I have a program that I am working on which would effectively convert binary, decimal, or hex numbers to other formats (don't ask why I'm doing this, I honestly don't know). So far I only have a binary - decimal conversion going, and it works fine however whenever the binary number entered is 8 digits or more it crashes.
As far as I can tell when I input the number 10011001 it gets translated to scientific notation and becomes 1.0011001E7 which wouldn't really be a problem, except that the way I am converting the numbers involves creating a string with the same value as the number and breaking it into individual characters. Unfortunately, this means I have a string valued "1.0011001E7" instead of "10011001", so when I cut up the characters I hit the "." and the program doesn't know what to do when I try to make calculations with that. So basically my question comes down to this, how do I force it to use the not-scientific notation version for these calculations?
Thanks for all your help, and here is the code if it helps at all:
//This Splits A Single String Of Digits Into An Array Of Individual Digits
public float[] splitDigits(float fltInput){
//This Declares The Variables
String strInput = "" + fltInput;
float[] digit = new float[strInput.length() - 2];
int m = 0;
//This Declares The Array To Hold The Answer
for (m = 0; m < (strInput.length() - 2); m++){
digit[m] = Float.parseFloat(strInput.substring(m, m + 1)); //Breaks here
}
//This Returns The Answer
return digit;
}
Just use BigDecimal
BigDecimal num = new BigDecimal(fltInput);
String numWithNoExponents = num.toPlainString();
Note here the fltInput will be automatically converted to a double.
I'm making a program that turns a large number into a string, and then adds the characters of that string up. It works fine, my only problem is that instead of having it as a normal number, Java converts my number into standard form, which makes it hard to parse the string. Are there any solutions to this?
public static void main(String ags[]) {
long nq = (long) Math.pow(2l, 1000l);
long result = 0;
String tempQuestion = Double.toString(nq);
System.out.println(tempQuestion);
String question = tempQuestion.substring(0, tempQuestion.length() - 2);
for (int count = 0; count < question.length(); count++) {
String stringResult = question.substring(count, count + 1);
result += Double.parseDouble(stringResult);
}
System.out.println(result);
Other answers are correct, you could use a java.text.NumberFormat (JavaDoc) to format your output. Using printfis also an option for formatting, similar to NumberFormat. But I see something else here. It looks like you mixed up your data types: In
nq = (long) Math.pow(2l, 1000l);
you are already truncating the double return value from Math to a long. Then you should use long as data type instead of double for the conversion. So use Long.toString(long), this will not add any exponent output.
Use Long.toString(nq) instead of Double.toString(nq); in your code.
As you say: "NumberFormat". The class.
BigInteger is easy to use and you don't risk precision problems with it. (In this particular instance I don't think there is a precision problem, because Math.pow(2, 1001) % 100000 returns the correct last 5 digits, but for bigger numbers eventually you will lose information.) Here's how you can use BigInteger:
groovy:000> b = new BigInteger(2L)
===> 2
groovy:000> b = b.pow(1001)
===> 214301721437253464189685009812000362112280962341106721488750077674070210224
98722449863967576313917162551893458351062936503742905713846280871969155149397149
60786913554964846197084214921012474228375590836430609294996716388253479753511833
1087892154125829142392955373084335320859663305248773674411336138752
groovy:000> ((b + "").toList().collect {new Integer(it)}).inject(0) {sum, n -> sum + n}
===> 1319
Here's the same thing in Java:
public class Example
{
public static void main(String[] args)
{
int sum = 0;
for (char ch : new java.math.BigInteger("2").pow(1001).toString().toCharArray()) {
sum += Character.digit(ch, 10);
}
System.out.println(sum);
}
}
Link to the javadoc for NumberFormat: Javadoc
just replace last line:
System.out.println(result);
with
System.out.printf("%d", result);
Getting following run-time error
C:\jdk1.6.0_07\bin>java euler/BigConCheck
Exception in thread "main" java.lang.NumberFormatException: For input string: "z
"
at java.lang.NumberFormatException.forInputString(NumberFormatException.
java:48)
at java.lang.Integer.parseInt(Integer.java:447)
at java.math.BigInteger.<init>(BigInteger.java:314)
at java.math.BigInteger.<init>(BigInteger.java:447)
at euler.BigConCheck.conCheck(BigConCheck.java:25)
at euler.BigConCheck.main(BigConCheck.java:71)
My Code
package euler;
import java.math.BigInteger;
class BigConCheck
{
public int[] conCheck(BigInteger big)
{
int i=0,q=0,w=0,e=0,r=0,t=0,mul=1;
int a[]= new int[1000];
int b[]= new int[7];
BigInteger rem[]= new BigInteger[4];
BigInteger num[]= new BigInteger[4];
for(i=0;i<4;i++)
num[i]=big; // intialised num[1 to 4][0] with big
String s="1",g="0";
for(i=0;i<999;i++)
s = s.concat(g);
BigInteger divi[]= new BigInteger[4];
for(i=0;i<5;i++)
{
divi[i]=new BigInteger(s);
int z = (int)Math.pow((double)10,(double)i);
BigInteger zz = new BigInteger("z"); // intialised div[1 to 4][0] with big
divi[i]=divi[i].divide(zz);
}
for(i=0;i<996;i++) // 5 consecative numbers.
{
for(int k=0;k<5;k++)
{
rem[k] = num[k].mod(divi[k]);
b[k]=rem[k].intValue();
mul= mul*b[k];
/*int z = (int)Math.pow((double)10,(double)(k+1));
String zz = "z";
BigInteger zzz = new BigInteger(zz);
num[k]=num[k].divide(zzz); */
}
a[i]=mul;
for(int p=0;p<5;p++)
{
BigInteger qq = new BigInteger("10");
num[p]=num[p].divide(qq);
}
}
return a;
}
public int bigestEleA(int u[])
{
int big=0;
for(int i=0;i<u.length;i++)
if(big<u[i])
big=u[i];
return big;
}
public static void main(String args[])
{
int con5[]= new int[1000];
int punCon;
BigInteger bigest = new BigInteger("7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450");
BigConCheck bcc = new BigConCheck();
con5=bcc.conCheck(bigest);
punCon=bcc.bigestEleA(con5);
System.out.println(punCon);
}
}
please point out whats goes wrong # runtime and why
thanks in advance...
This is the line causing you grief:
BigInteger zz = new BigInteger("z"); // intialised div[1 to 4][0] with big
While BigInteger does work with String's, those String's must be parsable into numbers.
EDIT**
Try this:
Integer z = (Integer)Math.pow((double)10,(double)i);
BigInteger zz = new BigInteger(z.toString());
new BigInteger("z"); is not meaningful. You can only pass numbers in constructor.
This is pretty obvious, so the next time you get an exception go the the exact line in your code shown in the exception stacktrace and you will most likely spot the problem.
BigInteger Javadoc states for BigInteger(String value)
Translates the decimal String
representation of a BigInteger into a
BigInteger. The String representation
consists of an optional minus sign
followed by a sequence of one or more
decimal digits. The character-to-digit
mapping is provided by
Character.digit. The String may not
contain any extraneous characters
(whitespace, for example).
So your code:
BigInteger zz = new BigInteger("z"); // intialised div[1 to 4][0] with big
is totally incorrect, but this is correct:
BigInteger zz = new BigInteger("5566");
EDIT: Based on your comment, this would be simpler by using the String.valueOf() method:
int z = (int)Math.pow((double)10,(double)i);
BigInteger zz = new BigInteger(String.valueOf(z));
BigInteger zz = new BigInteger("z");
you are passing non-numerical string thats the reason.
EDIT:
It takes string but it expects the string to be a numerical value. "z" does not have any numerical meaning.
Could it be that you want this instead?
int z = (int)Math.pow((double)10,(double)i);
BigInteger zz = new BigInteger(z);
Note the missing quotes here. (Of course, this will only work for i < 10.)
A common mistake is writing
new BigInteger("",num)
instead of
new BigInteger(""+num)
For those interested in generating longs with characters without hashing, it is possible to transform characters to long via BigInteger simply by using the constructor with a radix: BigInteger(String value, int radix)
There is a catch thought, the int which defines the log base, must scale not with the length of the String, but instead with the number of characters that make out the collection of characters that will be used in the creation of the String.
As far as I'm aware, for an alpha numeric collection, the int is 36 (26 + 10), this may be wrong thought.
There is also a limitation, I believe there are symbols that simply cannot be parsed, like "-" or " " or "_" (I've tried adding to the int base radix and nothing) which means the String must be transformed before parsing and it cannot be returned back to String after it being parsed via BigInteger.
Why is it useful?? I don't know haha, I have use it to autogenerate id's from Strings ,instead of using hashes, I remember somhwere this is kinda better than hashcode since a hash from String does not ensure uniqueness, an also this method as opposed to base Encoding gives extricity a long value, which may be useful for many api's that require a long id.