Karatsuba multiplication java recursion code not working? - java

I am trying to multiply two numbers using karatsuba multiplication. My java code is not working. I have used string as parameters and arguments so that we can multiply two n digit numbers (n is even). Also, I don't want to use long or BigInteger. Please help me to figure out my code mistake.
class karat{
public static String karatsuba(String first, String second){
if(first.length() <= 1 || second.length() <= 1)
return String.valueOf(Long.parseLong(first)*Long.parseLong(second));
String a = karatsuba(first.substring(0, first.length()/2), second.substring(0, second.length()/2));
String b = karatsuba(first.substring(first.length() - first.length()/2, first.length()), second.substring(second.length() - second.length()/2, second.length()));
String c = karatsuba(String.valueOf(Long.parseLong(first.substring(0, first.length()/2)) + Long.parseLong(first.substring(first.length() - first.length()/2, first.length()))), String.valueOf(Long.parseLong(second.substring(0, second.length()/2)) + Long.parseLong(second.substring(second.length() - second.length()/2, second.length()))));
String d = String.valueOf(Long.parseLong(c) - Long.parseLong(b) - Long.parseLong(a));
return String.valueOf(((int)Math.pow(10, first.length()))*(Long.parseLong(a)) + (((int)Math.pow(10, first.length()/2))*Long.parseLong(d)) + (Long.parseLong(c)));
}
public static void main(String[] args){
String result = karatsuba("1234", "5678");
System.out.println(result); }
}
Can you also please refine my code.
Numbers passed for multiplication - 1234 and 5678
Output is - 6655870 (Incorrect)
Output should be - 7006652 (Correct)
Thank you

First of all I tried look at your code, it gets a programmer to get lost, few things before we go into solution.
General advice. It is not good practice to convert string to value and back and forward like you do, it does not work like this. I tried as well to debug your code, it is just devil circle.
So I would start with check if value length and the maximum one.
Than if one of the values is less than 2 of length mean every thing less than 10 do multiplication otherwise do karatsuba recursion algorithm.
Here is the solution:
public static long karatsuba(long num1, long num2) {
int m = Math.max(
String.valueOf(num1).length(),
String.valueOf(num2).length()
);
if (m < 2)
return num1 * num2;
m = (m / 2) + (m % 2);
long b = num1 >> m;
long a = num1 - (b << m);
long d = num2 >> m;
long c = num2 - (d << m);
long ac = karatsuba(a, c);
long bd = karatsuba(b, d);
long abcd = karatsuba(a + b, c + d);
return ac + (abcd - ac - bd << m) + (bd << 2 * m);
}
Some test;
public static void main(String[] args) {
System.out.println(karatsuba(1, 9));
System.out.println(karatsuba(1234, 5678));
System.out.println(karatsuba(12345, 6789));
}
The output would be
9
7006652
83810205
It is less pain than your Stringish code. Btw, the solution is inspired from the pesudo in wiki and this class.

Interesting algorithm. One mistake is in
return String.valueOf(((int)Math.pow(10, first.length()))*(Long.parseLong(a)) + (((int)Math.pow(10, first.length()/2))*Long.parseLong(d)) + (Long.parseLong(c)));
At the end, it should be Long.parseLong(b) instead of Long.parseLong(c).
And in intermediate calculations, it can happen that the two strings are of different lengths. That also doesn't work correctly.
Please, allow some comments to improve the implementation. The idea to use strings seems to allow for big numbers, but then you introduce things like Long.parseLong() or (int)Math.pow(10, first.length()), limiting you to the long or int range.
If you really want to do big numbers, write your own String-based addition and power-of-ten multiplication (that one being trivial by appending some zeroes).
And, try to avoid names like a, b, c, or d - it's too easy to forget what they mean, as was your original mistake. E.g. the names from Wikipedia are a little bit better (using z0, z1 and z2), but still not perfect...

Related

How to calculate (a^b^c^d) mod 10^9+7?

i tried using this.
import java.io.*; // for handling input/output
import java.util.*; // contains Collections framework
// don't change the name of this class
// you can add inner classes if needed
class Main {
public static void main (String[] args) {
Scanner s=new Scanner(System.in);
int m=1000000007;
int a=s.nextInt();
int b=s.nextInt();
int c=s.nextInt();
int d=s.nextInt();
long temp1=power(c,d)%m;
long temp2= power(b,temp1)%m;
long result=power(a,temp2)%m;
System.out.println(result);
}
public static long power(int x, long n){
int m=1000000007;
if(n==0){
return 1;
}
if(n==1){
return x;
}
if(n%2==0){
return (power(x,n/2)*power(x,n/2))%m;
}else {
return ((power(x,n/2)*power(x,n/2))%m * x)%m;
}
}
}
but problem is when i increase size of a b c d then its showing TLE.
like for a=2 b=2 c=2 d=2 its giving output 65536 but when i take a=12 b=12 c=12 d=12 output should be 322269119 but using this it is showing Time limit exceed error. anyone can explain how to do this type of qurstion where it said that output value will be large so print is after doing mod 10^9+7.
Edit: a b c d values can be different.
The TLE is due to power recursively calling itself twice per invocation, so it expands to a full binary tree of calls (size: n) instead of into a nice linear chain of calls (length: log(n)) which is how Exponentiation by Squaring is supposed to work. In other words, it's exponentially slower than it needs to be, and for a very boring reason. Easy fix:
public static long power(int x, long n){
int m=1000000007;
if(n==0){
return 1;
}
if(n==1){
return x;
}
long p = power(x,n/2);
if(n%2==0){
return p * p % m;
}else {
return (p * p % m) * x % m;
}
}
But there is also a "math bug" in your program: abcd mod n is not equivalent to a^(b^(c^d mod n) mod n) mod n. Modular addition and multiplication work that way, but exponentiation has a different kind of periodicity.
Just using big integers naively is not sufficient, 12^12^12 would be a 4TB BigInteger, even on a computer that could handle that, computing or using such a physically large number would just take too long. But you can use Euler's theorem, and compute 12^12^12 mod φ(n). 12^12 is no big deal it even fits in a long, then 12 to the power of that long can be a modexp again but modulo φ(1E9+7) which is 1E9+6. For slightly larger c and d, c^d can also be computed as a BigInteger, as long as it isn't too big.
When c or d are so large that c^d is a problem even with BigIntegers, you can use more tricks to compute b^c^d mod φ(n) without the "full" c^d. Unfortunately Euler's theorem is not applicable to the "inner" exponentiation because the GCD of the modulus and the base may not be 1 (and isn't 1 in the example with the twelves), but there is a more complex expression that works in that case.

more efficient Fibonacci for BigInteger

I am working on a class project to create a more efficient Fibonacci than the recursive version of Fib(n-1) + Fib(n-2). For this project I need to use BigInteger. So far I have had the idea to use a map to store the previous fib numbers.
public static BigInteger theBigFib(BigInteger n) {
Map<BigInteger, BigInteger> store = new TreeMap<BigInteger, BigInteger>();
if (n.intValue()<= 2){
return BigInteger.ONE;
}else if(store.containsKey(n)){
return store.get(n);
}else{
BigInteger one = new BigInteger("1");
BigInteger two = new BigInteger("2");
BigInteger val = theBigFib(n.subtract(one)).add(theBigFib(n.subtract(two)));
store.put(n,val);
return val;
}
}
I think that the map is storing more than it should be. I also think this line
BigInteger val = theBigFib(n.subtract(one)).add(theBigFib(n.subtract(two)));
is an issue. If anyone could shed some light on what i'm doing wrong or possible another solution to make it faster than the basic code.
Thanks!
You don't need all the previous BigIntegers, you just need the last 2.
Instead of a recursive solution you can use a loop.
public static BigInteger getFib(int n) {
BigInteger a = new BigInteger.ONE;
BigInteger b = new BigInteger.ONE;
if (n < 2) {
return a;
}
BigInteger c = null;
while (n-- >= 2) {
c = a.add(b);
a = b;
b = c;
}
return c;
}
If you want to store all the previous values, you can use an array instead.
static BigInteger []memo = new BigInteger[MAX];
public static BigInteger getFib(int n) {
if (n < 2) {
return new BigInteger("1");
}
if (memo[n] != null) {
return memo[n];
}
memo[n] = getFib(n - 1).add(getFib(n - 2));
return memo[n];
}
If you just want the nth Fib value fast and efficient.
You can use the matrix form of fibonacci.
A = 1 1
1 0
A^n = F(n + 1) F(n)
F(n) F(n - 1)
You can efficiently calculate A^n using Exponentiation by Squaring.
I believe the main issue in your code is that you create a new Map on each function call. Note that it's still local variable, despite that your method is static. So, you're guaranteed that the store.containsKey(n) condition never holds and your solution is not better than naive. I.e. it still has exponential complexity of n. More precisely, it takes about F(n) steps to get to the answer (basically because all "ones" that make up your answer are returned by some function call).
I'd suggest making the variable a static field instead of a local variable. Then number of calls should become linear instead of exponential and you will see a significant improvement. Other solutions include for loop with three variables which iteratively calculate Fibonacci numbers from 0, 1, 2 up to n-th and the best solutions I know involve matrix exponentiation or explicit formula with real numbers (which is bad for precision), but it's a question better suited for computer science StackExchange website, imho.

Computing a series in Java?

I am trying to create a recursive method to compute a series in java 1/i.
Here is my code:
public static double computeSeries(int n) {
if (n == 1)
return 1;
else
return (1/n) + computeSeries(n - 1);
}
where 'n' is passed through the main method. However it doesn't exactly work correctly. FE when I type in 3, it returns 2.0, where I calculated it to be 1.8, and if I use 2, it gives me 1.0
While you're going to work with decimals, you might at least want to have a double as input
Solution
public static double computeSeries(double n)
However, if you only want the method to have an int as input, you might want to change 1/n to 1.0/n this will result to an operation of type double instead of int
This is called Promotion
JLS §5.6.2
If either operand is of type double, the other is converted to double.
First part of your result (1/n) is truncated to an int:
return (1/n) + computeSeries(n - 1);
Force calculations to be done in a double type by changing 1 to 1.0 (then it's a double):
return (1.0/n) + computeSeries(n - 1);
1/n
You are calculating in integers. This is always ZERO unless n == 1
Your first division will be 0 in most of the cases, since you're calculating with integers.
Instead use one of
return (1.0 / n) + computeSeries(n - 1);
return (1 / (double) n) + computeSeries(n - 1);
public static double computeSeries(double n) {
Bonus: You should take care of n = 0 to prevent a java.lang.ArithmeticException.
As most others have said, you need to convert the values to double before performing operations. Also, and this may just be personal preference, you may not want to have n calls of computeSeries running before they can all be completed.
Edit: After thinking more, using the for loop as I did below, there is no need for an extra method to calculate each term in the series. You can simply do the following
public static double computeSeries(int n) {
double sum = 0.0;
for(int i=1; i<=n; i++){
sum += (1.0/(double)i);
}
return sum;
}

Efficient BigInteger multiplication modulo n in Java

I can calculate the multiplication of two BigIntegers (say a and b) modulo n.
This can be done by:
a.multiply(b).mod(n);
However, assuming that a and b are of the same order of n, it implies that during the calculation, a new BigInteger is being calculated, and its length (in bytes) is ~ 2n.
I wonder whether there is more efficient implementation that I can use. Something like modMultiply that is implemented like modPow (which I believe does not calculate the power and then the modulo).
I can only think of
a.mod(n).multiply(b.mod(n)).mod(n)
and you seem already to be aware of this.
BigInteger has a toByteArray() but internally ints are used. hence n must be quite large to have an effect. Maybe in key generation cryptographic code there might be such work.
Furhtermore, if you think of short-cutting the multiplication, you'll get something like the following:
public static BigInteger multiply(BigInteger a, BigInteger b, int mod) {
if (a.signum() == -1) {
return multiply(a.negate(), b, mod).negate();
}
if (b.signum() == -1) {
return multiply(a, b.negate(), mod).negate();
}
int n = (Integer.bitCount(mod - 1) + 7) / 8; // mod in bytes.
byte[] aa = a.toByteArray(); // Highest byte at [0] !!
int na = Math.min(n, aa.length); // Heuristic.
byte[] bb = b.toByteArray();
int nb = Math.min(n, bb.length); // Heuristic.
byte[] prod = new byte[n];
for (int ia = 0; ia < na; ++ia) {
int m = ia + nb >= n ? n - ia - 1 : nb; // Heuristic.
for (int ib = 0; ib < m; ++ib) {
int p = (0xFF & aa[aa.length - 1 - ia]) * (0xFF & bb[bb.length - 1 - ib]);
addByte(prod, ia + ib, p & 0xFF);
if (ia + ib + 1 < n) {
addByte(prod, ia + ib + 1, (p >> 8) & 0xFF);
}
}
}
// Still need to do an expensive mod:
return new BigInteger(prod).mod(BigInteger.valueOf(mod));
}
private static void addByte(byte[] prod, int i, int value) {
while (value != 0 && i < prod.length) {
value += prod[prod.length - 1 - i] & 0xFF;
prod[prod.length - 1 - i] = (byte) value;
value >>= 8;
++i;
}
}
That code does not look appetizing. BigInteger has the problem of exposing the internal value only as big-endian byte[] where the first byte is the most significant one.
Much better would be to have the digits in base N. That is not unimaginable: if N is a power of 2 some nice optimizations are feasible.
(BTW the code is untested - as it does not seem convincingly faster.)
First, the bad news: I couldn't find any existing Java libraries that provided this functionality.
I couldn't find any pure-Java big integer libraries ... apart from java.math.BigInteger.
There are Java / JNI wrappers for the GMP library, but GMP doesn't implement this either.
So what are your options?
Maybe there is some pure-Java library that I missed.
Maybe there some other native (C / C++) big integer library supports this operation ... though you may need to write your own JNI wrappers.
You should be able to implement such a method for yourself, by copying the source code of java.math.BigInteger and adding an extra custom method. Alternatively, it looks like you could extend it.
Having said that, I'm not sure that there is a "substantially faster" algorithm for computing a * b mod n in Java, or any other language. (Apart from special cases; e.g. when n is a power of 2).
Specifically, the "Montgomery Reduction" approach wouldn't help for a single multiplication step. (The Wikipedia page says: "Because numbers have to be converted to and from a particular form suitable for performing the Montgomery step, a single modular multiplication performed using a Montgomery step is actually slightly less efficient than a "naive" one.")
So maybe the most effective way to speedup the computation would be to use the JNI wrappers for GMP.
You can use generic maths, like:
(A*B) mod N = ((A mod N) * (B mod N)) mod N
It may be more CPU intensive, but one should choose between CPU and memory, right?
If we are talking about modular arithmetic then indeed Montgomery reduction may be what you need. Don't know any out of box solutions though.
You can write a BigInteger multiplication as a standard long multiplication in a very large base -- for example, in base 2^32. It is fairly straightforward. If you want only the result modulo n, then it is advantageous to choose a base that is a factor of n or of which n is a factor. Then you can ignore all but one or a few of the lowest-order result (Big)digits as you perform the computation, saving space and maybe time.
That's most practical if you know n in advance, of course, but such pre-knowledge is not essential. It's especially nice if n is a power of two, and it's fairly messy if n is neither a power of 2 nor smaller than the maximum operand handled directly by the system's arithmetic unit, but all of those cases can be handled in principle.
If you must do this specifically with Java BigInteger instances, however, then be aware that any approach not provided by the BigInteger class itself will incur overhead for converting between internal and external representations.
Maybe this:
static BigInteger multiply(BigInteger c, BigInteger x)
{
BigInteger sum = BigInteger.ZERO;
BigInteger addOperand;
for (int i=0; i < FIELD_ELEMENT_BIT_SIZE; i++)
{
if (c.testBit(i))
addOperand = x;
else
addOperand = BigInteger.ZERO;
sum = add(sum, addOperand);
x = x.shiftRight(1);
}
return sum;
}
with the following helper functions:
static BigInteger add(BigInteger a, BigInteger b)
{
return modOrder(a.add(b));
}
static BigInteger modOrder(BigInteger n)
{
return n.remainder(FIELD_ORDER);
}
To be honest though, I'm not sure if this is really efficient at all since none of these operations are performed in-place.

Java rounding up to an int using Math.ceil

int total = (int) Math.ceil(157/32);
Why does it still return 4? 157/32 = 4.90625, I need to round up, I've looked around and this seems to be the right method.
I tried total as double type, but get 4.0.
What am I doing wrong?
You are doing 157/32 which is dividing two integers with each other, which always result in a rounded down integer. Therefore the (int) Math.ceil(...) isn't doing anything. There are three possible solutions to achieve what you want. I recommend using either option 1 or option 2. Please do NOT use option 0.
Option 0
Convert a and b to a double, and you can use the division and Math.ceil as you wanted it to work. However I strongly discourage the use of this approach, because double division can be imprecise. To read more about imprecision of doubles see this question.
int n = (int) Math.ceil((double) a / b));
Option 1
int n = a / b + ((a % b == 0) ? 0 : 1);
You do a / b with always floor if a and b are both integers. Then you have an inline if-statement which checks whether or not you should ceil instead of floor. So +1 or +0, if there is a remainder with the division you need +1. a % b == 0 checks for the remainder.
Option 2
This option is very short, but maybe for some less intuitive. I think this less intuitive approach would be faster than the double division and comparison approach:
Please note that this doesn't work for b < 0.
int n = (a + b - 1) / b;
To reduce the chance of overflow you could use the following. However please note that it doesn't work for a = 0 and b < 1.
int n = (a - 1) / b + 1;
Explanation behind the "less intuitive approach"
Since dividing two integers in Java (and most other programming languages) will always floor the result. So:
int a, b;
int result = a/b (is the same as floor(a/b) )
But we don't want floor(a/b), but ceil(a/b), and using the definitions and plots from Wikipedia:
With these plots of the floor and ceil functions, you can see the relationship.
You can see that floor(x) <= ceil(x). We need floor(x + s) = ceil(x). So we need to find s. If we take 1/2 <= s < 1 it will be just right (try some numbers and you will see it does, I find it hard myself to prove this). And 1/2 <= (b-1) / b < 1, so
ceil(a/b) = floor(a/b + s)
= floor(a/b + (b-1)/b)
= floor( (a+b-1)/b) )
This is not a real proof, but I hope you're satisfied with it. If someone can explain it better I would appreciate it too. Maybe ask it on MathOverflow.
157/32 is int/int, which results in an int.
Try using the double literal - 157/32d, which is int/double, which results in a double.
157/32 is an integer division because all numerical literals are integers unless otherwise specified with a suffix (d for double l for long)
the division is rounded down (to 4) before it is converted to a double (4.0) which is then rounded up (to 4.0)
if you use a variables you can avoid that
double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
int total = (int) Math.ceil((double)157/32);
Nobody has mentioned the most intuitive:
int x = (int) Math.round(Math.ceil((double) 157 / 32));
This solution fixes the double division imprecision.
In Java adding a .0 will make it a double...
int total = (int) Math.ceil(157.0 / 32.0);
When dividing two integers, e.g.,
int c = (int) a / (int) b;
the result is an int, the value of which is a divided by b, rounded toward zero. Because the result is already rounded, ceil() doesn't do anything. Note that this rounding is not the same as floor(), which rounds towards negative infinity. So, 3/2 equals 1 (and floor(1.5) equals 1.0, but (-3)/2 equals -1 (but floor(-1.5) equals -2.0).
This is significant because if a/b were always the same as floor(a / (double) b), then you could just implement ceil() of a/b as -( (-a) / b).
The suggestion of getting ceil(a/b) from
int n = (a + b - 1) / b;, which is equivalent to a / b + (b - 1) / b, or (a - 1) / b + 1
works because ceil(a/b) is always one greater than floor(a/b), except when a/b is a whole number. So, you want to bump it to (or past) the next whole number, unless a/b is a whole number. Adding 1 - 1 / b will do this. For whole numbers, it won't quite push them up to the next whole number. For everything else, it will.
Yikes. Hopefully that makes sense. I'm sure there's a more mathematically elegant way to explain it.
Also to convert a number from integer to real number you can add a dot:
int total = (int) Math.ceil(157/32.);
And the result of (157/32.) will be real too. ;)
int total = (int) Math.ceil( (double)157/ (double) 32);
Check the solution below for your question:
int total = (int) Math.ceil(157/32);
Here you should multiply Numerator with 1.0, then it will give your answer.
int total = (int) Math.ceil(157*1.0/32);
Use double to cast like
Math.ceil((double)value) or like
Math.ceil((double)value1/(double)value2);
Java provides only floor division / by default. But we can write ceiling in terms of floor. Let's see:
Any integer y can be written with the form y == q*k+r. According to the definition of floor division (here floor) which rounds off r,
floor(q*k+r, k) == q , where 0 ≤ r ≤ k-1
and of ceiling division (here ceil) which rounds up r₁,
ceil(q*k+r₁, k) == q+1 , where 1 ≤ r₁ ≤ k
where we can substitute r+1 for r₁:
ceil(q*k+r+1, k) == q+1 , where 0 ≤ r ≤ k-1
Then we substitute the first equation into the third for q getting
ceil(q*k+r+1, k) == floor(q*k+r, k) + 1 , where 0 ≤ r ≤ k-1
Finally, given any integer y where y = q*k+r+1 for some q,k,r, we have
ceil(y, k) == floor(y-1, k) + 1
And we are done. Hope this helps.
There are two methods by which you can round up your double value.
Math.ceil
Math.floor
If you want your answer 4.90625 as 4 then you should use Math.floor and if you want your answer 4.90625 as 5 then you can use Math.ceil
You can refer following code for that.
public class TestClass {
public static void main(String[] args) {
int floorValue = (int) Math.floor((double)157 / 32);
int ceilValue = (int) Math.ceil((double)157 / 32);
System.out.println("Floor: "+floorValue);
System.out.println("Ceil: "+ceilValue);
}
}
I know this is an old question but in my opinion, we have a better approach which is using BigDecimal to avoid precision loss. By the way, using this solution we have the possibility to use several rounding and scale strategies.
final var dividend = BigDecimal.valueOf(157);
final var divisor = BigDecimal.valueOf(32);
final var result = dividend.divide(divisor, RoundingMode.CEILING).intValue();
int total = (157-1)/32 + 1
or more general
(a-1)/b +1

Categories