Storing result of multiplication of two integers in long - java

I solved a programming question where I had to find the number of 1's in the binary form of the product if 2 numbers A and B. The range of A and B was [0, 10^9] inclusive.
Here is the code I wrote.
public class Solution {
public static void main(String[] args) {
// System.out.println(solution(32329,4746475));
System.out.println(solution(3,4));
}
public static int solution(int A, int B) {
// write your code in Java SE 8
long mul=A*B;
int ans=0;
while(mul>0)
{
if((mul%2)!=0)
{
ans++;
}
mul=mul/2;
}
return ans;
}
}
This worked fine for the input (3,4) but, when I tried (32329,4746475) as input instead the code didn't work and it showed 0 as answer.
I put in a few output statements at different places to debug and found that with this input, the result of multiplication comes out to be -1170032381 (which is wrong) and therefore, the while loop's condition fails. So, I type-casted both A and B like so
long mul=(long)A*(long)B;
And voila it worked. Now, my question is why?
Why did the code work fine for smaller inputs and flop for larger ones and shouldn't 'int to long' be implicit type casting in Java?
(I also tried a few other inputs so not all larger ones give negative as the product but they don't give the correct answer either, smaller ones I've tried till 5-digit A and B give the correct product)

Java has automatic widening from int to long, but that happens at assignment, but the multiplication of an int with another int produces an int, so you would get integer overflow first multiplying 32329 with 4746475, then the widening of the overflowed int result to long.
However, if you first cast at least one of the int to long, then the multiplication is done using long and the result is long, so no integer overflow.

Java int can store from
-2147483648 to 2147483647
32329 X 4746475 =153448790275
as Java does the multiplication before the implicit conversion the result is wrong

Related

Arithmetic Operation in Java

Assume that I have one arithmetic function which will add two long variables and return a long value. If pass Long.MaxValue() as an argument it wont give a perfect result. What will be the solution for that? The code below explains what I mean:
public class ArithmaticExample {
public static void main(String[] args) {
System.out.println(ArithmaticExample.addLong(Long.MAX_VALUE, Long.MAX_VALUE));
}
public static long addLong(long a,long b){
return a+b;
}
}
So you can see the wood from the trees, let's recast the problem using byte rather than long and consider
byte a = 0b01111111; // i.e. 127, the largest value of a `byte`.
byte b = 0b01111111;
byte c = (byte)(a + b);
where you need the explicit cast to circumvent conversion of a + b to an int.
Computing c by hand gives you 0b11111110. This is, of course, the bitwise representation of -2 in an 8 bit 2's complement type.
So the answer for the byte case is -2. And the same holds true for a long: there are just more 1 bits to contend with in your addition.
Note that although all this is perfectly well-defined in Java, the same cannot be said for C and C++.
If you need to add two long values of such magnitude then consider using BigInteger.
The result is -2. This is not what is expected as it seems to be more an overflow than anything else, but this result is "normal".
Long.MAX_VALUE = 9223372036854775807
Long.MAX_VALUE + 1 = 9223372036854775807
Long.MAX_VALUE + Long.MAX_VALUE = -2

Project Euler #8 in java

The challenge is listed here:
The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?
I have written a code that works with the given 4 digit example, but doesn't work for 13 digits. I suspect there is some type of data overflow, but I am unsure. My super inefficient code is below.
public class Euler8 {
public static void main(String[]args){
String num = "/*number listed above*/";
int n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13;
long sum=0, newSum;
for(int n=0; n<=987; n++){
n1=Character.getNumericValue(num.charAt(n));
n2=Character.getNumericValue(num.charAt(n+1));
n3=Character.getNumericValue(num.charAt(n+2));
n4=Character.getNumericValue(num.charAt(n+3));
n5=Character.getNumericValue(num.charAt(n+4));
n6=Character.getNumericValue(num.charAt(n+5));
n7=Character.getNumericValue(num.charAt(n+6));
n8=Character.getNumericValue(num.charAt(n+7));
n9=Character.getNumericValue(num.charAt(n+8));
n10=Character.getNumericValue(num.charAt(n+9));
n11=Character.getNumericValue(num.charAt(n+10));
n12=Character.getNumericValue(num.charAt(n+11));
n13=Character.getNumericValue(num.charAt(n+12));
newSum= (long)(n1*n2*n3*n4*n5*n6*n7*n8*n9*n10*n11*n12*n13);
if(newSum>=sum)
sum=newSum;
}
System.out.println(sum);
}
}
My code outputs this number:
2091059712
Your code makes a cast to long too late: by the time the cast is performed, the multiplication has been completed in 32-bit integers, predictably causing an overflow.
Change the code as follows to fix the problem:
// newSum should be called newProd, because you use multiplication, not addition
newSum= ((long)n1)*n2*n3*n4*n5*n6*n7*n8*n9*n10*n11*n12*n13;
Note that your algorithm is not the most efficient: you could do it 13 times faster if you observe that the product for positions i+1..i+13 can be computed from the product for positions i..i+12 by dividing the value at position i and multiplying by the value at position i+13.
Of course you would have to be careful not to divide by zero. You can work around this by observing that any time you encounter a zero, the next 13 products would all be zero, so you could simply skip them, and move on to the next "train" of non-zeros.
The problem is that n1*n2*n3*n4*n5*n6*n7*n8*n9*n10*n11*n12*n13 overflows because:
they are all int variables, and
an int multiplied by an int gives an int.
The typecase to long is applied to the entire product, and (therefore) happens too late to cause the computations to be done with long arithmetic and avoid the overflow problem.
The simple solution to that particular problem is to declare the n variables as long. It is possible that #dasblinkelights' code (casting n1) is faster ... but you would need to benchmark it to be sure. And there are more significant optimizations than that.
I get the answer as 23514624000 . which is actually correct.
public class LargestProduct {
public static void main(String[]args) {
String s="7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
long k=0,l=13,ans=1,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13;
long Max_Num=0;
String[] result=new String[1000];
result=s.split("");
for(int i=0;i<=987;i++) {
n1=Integer.parseInt(result[i]);
n2=Integer.parseInt(result[i+1]);
n3=Integer.parseInt(result[i+2]);
n4=Integer.parseInt(result[i+3]);
n5=Integer.parseInt(result[i+4]);
n6=Integer.parseInt(result[i+5]);
n7=Integer.parseInt(result[i+6]);
n8=Integer.parseInt(result[i+7]);
n9=Integer.parseInt(result[i+8]);
n10=Integer.parseInt(result[i+9]);
n11=Integer.parseInt(result[i+10]);
n12=Integer.parseInt(result[i+11]);
n13=Integer.parseInt(result[i+12]);
ans=n1*n2*n3*n4*n5*n6*n7*n8*n9*n10*n11*n12*n13;
Max_Num=Math.max(Max_Num, ans);
}
System.out.println(Max_Num);
}
}

Converting long to int gives 0

I have been testing out with this snippet of code:
public class Test {
public static int longToInt(long num) {
return (int) (num);
}
public static void main(String[] args) {
System.out.println(longToInt(100000000L));
}
}
I ran it but longToInt only returned 0. What is going on?
Casting a long to an int is done by removing the top 32 bits of the long. If the long value is larger than Integer.MAX_VALUE (2147483647) or smaller than Integer.MIN_VALUE (-2147483648), the net effect is that you lose significant bits, and the result is "rubbish".
Having said that, the code you supplied does not behave like you say it does ... if you compile and run it correctly. The original version should print an unexpected number ... but not zero. The modified version should print 1000000 as expected.
... is there a way I can store a long number larger than Integer.MAX_VALUE inside an int number?
No.
Well strictly yes ... in some circumstances. You could do something to map the numbers, For example, if you know that your numbers are always in the range A to B, and B - A is less than 232, then you could map a long in that range to an int by subtracting A from it.
However, it is mathematically impossible to define such a mapping if the size of the domain of numbers you are storing in the long is larger than 232. Which it typically is.
because, the long you gave doesn't fit into int. Give a smaller long and try !
int (32 bits)
long (64 bits)

Number at f(93) in fibonacci series has negative value, how?

I am trying to printout fibonacci series upto 'N' numbers. All works as per expectation till f(92) but when I am trying to get the value of f(93), values turns out in negative: "-6246583658587674878". How this could be possible? What is the mistake in the logic below?
public long fibo(int x){
long[] arr = new long[x+1];
arr[0]=0;
arr[1]=1;
for (int i=2; i<=x; i++){
arr[i]=arr[i-2]+arr[i-1];
}
return arr[x];
}
f(91) = 4660046610375530309
f(92) = 7540113804746346429
f(93) = -6246583658587674878
Is this because of data type? What else data type I should use for printing fibonacci series upto N numbers? N could be any integer within range [0..10,000,000].
You've encountered an integer overflow:
4660046610375530309 <-- term 91
+7540113804746346429 <-- term 92
====================
12200160415121876738 <-- term 93: the sum of the previous two terms
9223372036854775808 <-- maximum value a long can store
To avoid this, use BigInteger, which can deal with an arbitrary number of digits.
Here's your implementation converted to use BigDecimal:
public String fibo(int x){
BigInteger[] arr = new BigInteger[x+1];
arr[0]=BigInteger.ZERO;
arr[1]=BigInteger.ONE;
for (int i=2; i<=x; i++){
arr[i]=arr[i-2].add(arr[i-1]);
}
return arr[x].toString();u
}
Note that the return type must be String (or BigInteger) because even the modest value of 93 for x produces a result that is too great for any java primitive to represent.
This happened because the long type overflowed. In other words: the number calculated is too big to be represented as a long, and because of the two's complement representation used for integer types, after an overflow occurs the value becomes negative. To have a better idea of what's happening, look at this code:
System.out.println(Long.MAX_VALUE);
=> 9223372036854775807 // maximum long value
System.out.println(Long.MAX_VALUE + 1);
=> -9223372036854775808 // oops, the value overflowed!
The value of fibo(93) is 12200160415121876738, which clearly is greater than the maximum value that fits in a long.
This is the way integers work in a computer program, after all they're limited and can not be infinite. A possible solution would be to use BigInteger to implement the method (instead of long), it's a class for representing arbitrary-precision integers in Java.
As correctly said in above answers, you've experienced overflow, however with below java 8 code snippet you can print series.
Stream.iterate(new BigInteger[] {BigInteger.ZERO, BigInteger.ONE}, t -> new BigInteger[] {t[1], t[0].add(t[1])})
.limit(100)
.map(t -> t[0])
.forEach(System.out::println);

Interesting thing happening when I take a number, multiply it by 10, and then add 1 [duplicate]

This question already has answers here:
Multiplication of two ints overflowing to result in a negative number
(5 answers)
Closed 9 years ago.
static int fn = 0;
static int sn = 0;
static boolean running = false;
public static void run()
{
while (running == true)
{
fn = numbers[0];
sn = numbers[1];
if (sign == 0)
{
input.setText(String.valueOf(fn));
}
}
}
static class one implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (Display.sign == 0)
{
Display.numbers[0] = Display.numbers[0] *10;
Display.numbers[0] = Display.numbers[0] +1;
}
}
}
This is the code for a calculator that I am programming (not all of it of course). This is the part where I display the number on the screen which I have done, but weirdly this works up until 10 characters
So after I get the program to display 1111111111 I want to do it once more and it gives me this weird number -1773790777. I am confused about how the program comes up with this. As you can see, above Display.numbers[] is the array I am storing the two numbers in. So to go over a place I multiply the number in the array by 10 then add 1. So how does this give me a negative number in the first place and what can I do to solve this problem?
Is your number overflowing?
You can check it by looking at Integer.MAX_VALUE (assuming you are using an integer). If you go over that you will loop will get weird results like this. See - http://javapapers.com/core-java/java-overflow-and-underflow/ for more details.
It's overflowing!
1111111111*10 + 1 = 11111111111 which is 0x2964619C7 in hexadecimal. It's a 34-bit value which can't be stored in a 32-bit int
In Java arithmetic operations wrap around by default, so if the result overflowed then it'll be wrapped back to the other end of the value range. See How does Java handle integer underflows and overflows and how would you check for it?
However due to the use of 2's complement, the result will be the lower bits of the result 11111111111 mod 232 = 2521176519 = 0x964619C7 which is -1'773'790'777 in 32-bit int, that's why you see the number. You should read more on binary, that's the basic of nowadays computers
In Java 8 you'll have an easier way to detect overflow with the new *Exact methods
The platform uses signed two's complement integer arithmetic with int and long primitive types. The developer should choose the primitive type to ensure that arithmetic operations consistently produce correct results, which in some cases means the operations will not overflow the range of values of the computation. The best practice is to choose the primitive type and algorithm to avoid overflow. In cases where the size is int or long and overflow errors need to be detected, the methods addExact, subtractExact, multiplyExact, and toIntExact throw an ArithmeticException when the results overflow. For other arithmetic operations such as divide, absolute value, increment, decrement, and negation overflow occurs only with a specific minimum or maximum value and should be checked against the minimum or maximum as appropriate.
https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html

Categories

Resources