Karatsuba Algorithm without BigInteger in Java, unexpected behaviour while recursion - java

So I want to run Karatsuba Algorithm without using class BigInteger in Java, so upon following the pseudo-code and this question, I came with the following code
public static long recKaratsuba(long i1, long i2){
if(i1<10 || i2<10) {
return i1*i2 ;
}
long len = Math.round(Long.toString(Math.max(i1,i2)).length());
long N = Math.round(len/2) ;
long b = (long) (i1% Math.pow(10, N)) ;
long a = (long) (i1/ Math.pow(10,N));
long d = (long) (i2% Math.pow(10,N)) ;
long c = (long) (i2/ Math.pow(10,N));
//System.out.println("a,b,c,d :" + a + b + c + d);
long ac = recKaratsuba(a, c) ;
long bd = recKaratsuba(b, d) ;
long pos = recKaratsuba(a+b,c+d) ;
return ((long)(bd + ac*Math.pow(10,len) + (pos -ac -bd)*Math.pow(10,N) )) ;
}
Now, the problem with this is that it's producing the wrong answer, 1234*5678 is giving 11686652, which should've been 7006652.
As a beginner to Java and algorithms, I am unable to pinpoint the exact bug in this code, also I do realize that this program is very inefficient and doesn't work for more than 4 digits (according to the linked question ). But this is intuitively what I came up with originally after learning the pseudo-code.
So my question is, what is the problem in my code and how do I execute the following algorithm without using the BigInteger method?

There are a few things i notice:
Instead of i1 and i2 maybe use x and y
Variables len and N are int, not long
No need to round the maximum of the lengths of the string-representations: Lengths are ints, ints are whole numbers and cant be rounded
No need to round the division by 2: Dividing a whole number will always result in a whole number (integer division is done)
The error is in the return-statement: Math.pow(10, len) should be Math.pow(10, 2 * N) instead, this is important if N is uneven
Avoid multiple identical calculations: especially Math.pow(10, N)
The fixed code gives the correct results for all examples that i have tested.
public static long recKaratsuba2(long x, long y) {
if (x < 10 || y < 10) {
return x * y;
}
int len = Long.toString(Math.max(x, y)).length();
double den = Math.pow(10, len / 2);
long a = (long) (x / den);
long b = (long) (x % den);
long c = (long) (y / den);
long d = (long) (y % den);
long ac = recKaratsuba2(a, c);
long bd = recKaratsuba2(b, d);
long pos = recKaratsuba2(a + b, c + d);
return (long) (bd + den * (ac * den + (pos - ac - bd)));
}

Related

How to get the correct output in Modulo (10^9 + 7) format?

I am working on this code challenge:
Problem Description
Given 2 integers x and n, you have to calculate x
to the power of n, modulo 10^9+7 i.e. calculate (x^n) % (10^9+7).
In other words, you have to find the value when x is raised to the
power of n, and then modulo is taken with 10^9+7.
a%b means the remainder when a divides b. For instance, 5%3 = 2, as
when we divide 5 by 3, 2 is the remainder.
Note that 10^9 is also represented as 1e9.
Input format
One line of input containing two space separated
integers, x and n.
Output format Print the required answer.
Sample Input 1 100000000 2
Sample Output 1 930000007
Explanation 1 (10^8)^2 = 10^16
10^16 % (10^9+7) = 930000007
Constraints 0 <= x < 10^9
0 <= n < 10^5
Code
The following is my code:
import java.util.*;
class ModularExponentiation {
// NOTE: Please do not modify this function
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
int n = sc.nextInt();
int ans = modularExponentiation(x, n);
System.out.println(ans);
}
// TODO: Implement this method
static int modularExponentiation(int x, int n) {
int M = 1000000007;
long a = (long) Math.pow(x, n);
long b = a%M;
return (int)b;
}
}
When I run my code, it succeeds for the sample test case and an edge case, but fails for 3 base cases. How do I make my code succeed all test cases?
Does this work?
public static int modularExponentiation(int x, int n) {
int modulo = 1000000007;
if (n == 0) {
return 1;
} else if (n == 1) {
return x % modulo;
} else if (n == -1) {
return 1 / x;
}
int p = modularExponentiation(x, n >> 1);
long product = ((long) p * p) % modulo;
return (int) (product * modularExponentiation(x, n & 1) % modulo);
}
Key points:
Math.pow(x,n) suffers from overflow and we can't compensate that overflow relying on result only, that is why initial idea of Math.pow(x,n) % modulo produces wrong results
We may notice that (x * x) % modulo == (x % modulo) * (x % modulo) % modulo, and it is safe to use long here as intermediate result because x % modulo < modulo and modulo * modulo < 2^63 - 1
We need to reconstruct the process, but naive approach that x^n is a product of n x's is too slow - it has O(N) time complexity, however we may notice that x^2k == (x^k)^2 and x^(2k+1) == x * (x^k)^2 - so we may use either recursion here or loop to achieve O(LogN) time complexity
alternative loop solution:
public static int modularExponentiation(int x, int n) {
int modulo = 1000000007;
long product = 1;
long p = x;
while (n != 0) {
if ((n & 1) == 1) {
product = product * p % modulo;
}
p = (p * p % modulo);
n >>= 1;
}
return (int) product;
}
If you have problem in C++ then , you can use
const unsigned int Mod=1e9+7;

Understanding the strictMath java library

I got bored and decided to dive into remaking the square root function without referencing any of the Math.java functions. I have gotten to this point:
package sqrt;
public class SquareRoot {
public static void main(String[] args) {
System.out.println(sqrtOf(8));
}
public static double sqrtOf(double n){
double x = log(n,2);
return powerOf(2, x/2);
}
public static double log(double n, double base)
{
return (Math.log(n)/Math.log(base));
}
public static double powerOf(double x, double y) {
return powerOf(e(),y * log(x, e()));
}
public static int factorial(int n){
if(n <= 1){
return 1;
}else{
return n * factorial((n-1));
}
}
public static double e(){
return 1/factorial(1);
}
public static double e(int precision){
return 1/factorial(precision);
}
}
As you may very well see, I came to the point in my powerOf() function that infinitely recalls itself. I could replace that and use Math.exp(y * log(x, e()), so I dived into the Math source code to see how it handled my problem, resulting in a goose chase.
public static double exp(double a) {
return StrictMath.exp(a); // default impl. delegates to StrictMath
}
which leads to:
public static double exp(double x)
{
if (x != x)
return x;
if (x > EXP_LIMIT_H)
return Double.POSITIVE_INFINITY;
if (x < EXP_LIMIT_L)
return 0;
// Argument reduction.
double hi;
double lo;
int k;
double t = abs(x);
if (t > 0.5 * LN2)
{
if (t < 1.5 * LN2)
{
hi = t - LN2_H;
lo = LN2_L;
k = 1;
}
else
{
k = (int) (INV_LN2 * t + 0.5);
hi = t - k * LN2_H;
lo = k * LN2_L;
}
if (x < 0)
{
hi = -hi;
lo = -lo;
k = -k;
}
x = hi - lo;
}
else if (t < 1 / TWO_28)
return 1;
else
lo = hi = k = 0;
// Now x is in primary range.
t = x * x;
double c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
if (k == 0)
return 1 - (x * c / (c - 2) - x);
double y = 1 - (lo - x * c / (2 - c) - hi);
return scale(y, k);
}
Values that are referenced:
LN2 = 0.6931471805599453, // Long bits 0x3fe62e42fefa39efL.
LN2_H = 0.6931471803691238, // Long bits 0x3fe62e42fee00000L.
LN2_L = 1.9082149292705877e-10, // Long bits 0x3dea39ef35793c76L.
INV_LN2 = 1.4426950408889634, // Long bits 0x3ff71547652b82feL.
INV_LN2_H = 1.4426950216293335, // Long bits 0x3ff7154760000000L.
INV_LN2_L = 1.9259629911266175e-8; // Long bits 0x3e54ae0bf85ddf44L.
P1 = 0.16666666666666602, // Long bits 0x3fc555555555553eL.
P2 = -2.7777777777015593e-3, // Long bits 0xbf66c16c16bebd93L.
P3 = 6.613756321437934e-5, // Long bits 0x3f11566aaf25de2cL.
P4 = -1.6533902205465252e-6, // Long bits 0xbebbbd41c5d26bf1L.
P5 = 4.1381367970572385e-8, // Long bits 0x3e66376972bea4d0L.
TWO_28 = 0x10000000, // Long bits 0x41b0000000000000L
Here is where I'm starting to get lost. But I can make a few assumptions that so far the answer is starting to become estimated. I then find myself here:
private static double scale(double x, int n)
{
if (Configuration.DEBUG && abs(n) >= 2048)
throw new InternalError("Assertion failure");
if (x == 0 || x == Double.NEGATIVE_INFINITY
|| ! (x < Double.POSITIVE_INFINITY) || n == 0)
return x;
long bits = Double.doubleToLongBits(x);
int exp = (int) (bits >> 52) & 0x7ff;
if (exp == 0) // Subnormal x.
{
x *= TWO_54;
exp = ((int) (Double.doubleToLongBits(x) >> 52) & 0x7ff) - 54;
}
exp += n;
if (exp > 0x7fe) // Overflow.
return Double.POSITIVE_INFINITY * x;
if (exp > 0) // Normal.
return Double.longBitsToDouble((bits & 0x800fffffffffffffL)
| ((long) exp << 52));
if (exp <= -54)
return 0 * x; // Underflow.
exp += 54; // Subnormal result.
x = Double.longBitsToDouble((bits & 0x800fffffffffffffL)
| ((long) exp << 52));
return x * (1 / TWO_54);
}
TWO_54 = 0x40000000000000L
While I am, I would say, very understanding of math and programming, I hit the point to where I find myself at a Frankenstein monster mix of the two. I noticed the intrinsic switch to bits (which I have little to no experience with), and I was hoping someone could explain to me the processes that are occurring "under the hood" so to speak. Specifically where I got lost is from "Now x is in primary range" in the exp() method on wards and what the values that are being referenced really represent. I'm was asking for someone to help me understand not only the methods themselves, but also how they arrive to the answer. Feel free to go as in depth as needed.
edit:
if someone could maybe make this tag: "strictMath" that would be great. I believe that its size and for the Math library deriving from it justifies its existence.
To the exponential function:
What happens is that
exp(x) = 2^k * exp(x-k*log(2))
is exploited for positive x. Some magic is used to get more consistent results for large x where the reduction x-k*log(2) will introduce cancellation errors.
On the reduced x a rational approximation with minimized maximal error over the interval 0.5..1.5 is used, see Pade approximations and similar. This is based on the symmetric formula
exp(x) = exp(x/2)/exp(-x/2) = (c(x²)+x)/(c(x²)-x)
(note that the c in the code is x+c(x)-2). When using Taylor series, approximations for c(x*x)=x*coth(x/2) are based on
c(u)=2 + 1/6*u - 1/360*u^2 + 1/15120*u^3 - 1/604800*u^4 + 1/23950080*u^5 - 691/653837184000*u^6
The scale(x,n) function implements the multiplication x*2^n by directly manipulating the exponent in the bit assembly of the double floating point format.
Computing square roots
To compute square roots it would be more advantageous to compute them directly. First reduce the interval of approximation arguments via
sqrt(x)=2^k*sqrt(x/4^k)
which can again be done efficiently by directly manipulating the bit format of double.
After x is reduced to the interval 0.5..2.0 one can then employ formulas of the form
u = (x-1)/(x+1)
y = (c(u*u)+u) / (c(u*u)-u)
based on
sqrt(x)=sqrt(1+u)/sqrt(1-u)
and
c(v) = 1+sqrt(1-v) = 2 - 1/2*v - 1/8*v^2 - 1/16*v^3 - 5/128*v^4 - 7/256*v^5 - 21/1024*v^6 - 33/2048*v^7 - ...
In a program without bit manipulations this could look like
double my_sqrt(double x) {
double c,u,v,y,scale=1;
int k=0;
if(x<0) return NaN;
while(x>2 ) { x/=4; scale *=2; k++; }
while(x<0.5) { x*=4; scale /=2; k--; }
// rational approximation of sqrt
u = (x-1)/(x+1);
v = u*u;
c = 2 - v/2*(1 + v/4*(1 + v/2));
y = 1 + 2*u/(c-u); // = (c+u)/(c-u);
// one Halley iteration
y = y*(1+8*x/(3*(3*y*y+x))) // = y*(y*y+3*x)/(3*y*y+x)
// reconstruct original scale
return y*scale;
}
One could replace the Halley step with two Newton steps, or
with a better uniform approximation in c one could replace the Halley step with one Newton step, or ...

Check if a double = 1/3

I have made a function that converts a double to a simplified fraction in Java:
public static int gcm(int a, int b) {
return b == 0 ? a : gcm(b, a % b);
}
public static String toFraction(double d) {
int decimals = String.valueOf(d).split("\\.")[1].length();
int mult = (int) Math.pow(10, decimals);
int numerator = (int) (d * mult);
int denominator = mult;
// now simplify
int gcm = gcm(numerator, denominator);
numerator /= gcm;
denominator /= gcm;
return numerator + "/" + denominator;
}
It works, except for the fact that if I use toFraction(1.0/3), this will, understandably, return "715827882/2147483647". How may I fix this to return "1/3"?
You have to allow for a certain error and not all fractions can be exactly represented as scalar values.
public static String toFraction(double d, double err) {
String s = Long.toString((long) d);
d -= (long) d;
if (d > err) {
for (int den = 2, max = (int) (1 / err); den < max; den++) {
long num = Math.round(d * den);
double d2 = (double) num / den;
if (Math.abs(d - d2) <= err)
return (s.equals("0") ? "" : s + " ") + num +"/"+den;
}
}
return s;
}
public static void main(String... args) {
System.out.println(toFraction(1.0/3, 1e-6));
System.out.println(toFraction(1.23456789, 1e-6));
System.out.println(toFraction(Math.E, 1e-6));
System.out.println(toFraction(Math.PI, 1e-6));
for (double d = 10; d < 1e15; d *= 10)
System.out.println(toFraction(Math.PI, 1.0 / d));
}
prints
1/3
1 19/81
2 719/1001
3 16/113
3 1/5
3 1/7
3 9/64
3 15/106
3 16/113
3 16/113
3 3423/24175
3 4543/32085
3 4687/33102
3 14093/99532
3 37576/265381
3 192583/1360120
3 244252/1725033
3 2635103/18610450
Note: this finds the 21/7, 333/106 and 355/113 approximations for PI.
No double value is equal to one third, so the only way your program can be made to print 1/3 is if you change the specification of the method to favour "nice" answers rather than the answer that is technically correct.
One thing you could do is choose a maximum denominator for the answers, say 100, and return the closest fraction with denominator 100 or less.
Here is how you could implement this using Java 8 streams:
public static String toFraction(double val) {
int b = IntStream.rangeClosed(1, 100)
.boxed()
.min(Comparator.comparingDouble(n -> Math.abs(val * n - Math.round(val * n))))
.get();
int a = (int) Math.round(val * b);
int h = gcm(a, b);
return a/h + "/" + b/h;
}
There is no nice approach to this. double is not very good for this sort of thing. Note that BigDecimal can't represent 1/3 either, so you'll have the same problem with that class.
There are nice ways to handle this but you will need to look at special cases. For example, if the numerator is 1 then the fraction is already reduced and you simply strip out the decimal places and return what you were given.

Java- Get decimal at position n

What is the best way to get the decimal at position n from a float (by cutting out everything from the number except that decimal)?
It should work like this:
getDecimal(3.654987, 4) => returns 0.0009
getDecimal(3.654987, 2) => returns 0.05
Float f = new Float("0.123456789");
System.out.println(f.toString().charAt(5));
Prints 4. Try in this direction.
This should work for you:
public static double getDecimal(double num, int n) {
return ((int) (num * Math.pow(10, (double) n)) % 10) * Math.pow(10, (double) -n);
}
Assuming the position will be always a positive integer(> 0):
float input = 3.654987f;
int pos = 4;
String op = String.valueOf(input).replaceAll("\\d*\\.\\d{"+(pos-1)+"}(\\d)\\d+",
"0." + new String(new char[pos-1]).replace("\0", "0") + "$1");
System.out.println(op);

how to implement hash function `h(k) = (A·k mod 2^w) >> (w – r)` in Java

IMPORTANT NOTICE:
This is not a discussion thread for people to give me their opinion about hashing. I just need to know how to make the given function work in java -- an example would be best.
PROBLEM:
Trying to hone my understanding of hash functions for a pending interview, I watch two free lectures by MIT computer science professors (http://videolectures.net/mit6046jf05_leiserson_lec08/). So after the lecture, I am trying to implement the following hash function in java.
h(k) = (A·k mod 2^w) >> (w – r)
WHERE
r: m, the size of the array, is a power of 2 such that m=2^r
w: the computer has w-bit words, such as 32-bit or 64-bit computer
k: the value I am to find a key for
A: a random odd number (prime would be great) between 2^(w-1) and 2^w
I thought this would be easy to implement in java. But when I do 2^w where w=32, I get inaccurate results in Java. In real life 2^32 = 4294967296 but not in java, which truncates the result to 2^31 - 1 or 2147483647.
Does anyone know how to fix this problem so to implement the function in Java?
EDIT:
I see a lot of the replies focus on 32. What if my computer is 64 bit? I am stuck with setting w = 32 because I am using Java?
Some of the terms are redundant because Java assumes this behaviour anyway.
A·k mod 2^w
In Java, integer multiplication overflows and thus does a mod 2^w (with a sign). The fact that it has a sign doesn't matter if you are then shifting by at least one bit.
Shift of (w - r) is the same as a shift of -r in Java (the w is implied by the type)
private static final int K_PRIME = (int) 2999999929L;
public static int hash(int a, int r) {
// return (a * K_PRIME % (2^32)) >>> (32 - r);
return (a * K_PRIME) >>> -r;
}
for 64-bit
private static final long K_PRIME = new BigInteger("9876534021204356789").longValue();
public static long hash(long a, int r) {
// return (a * K_PRIME % (2^64)) >>> (64 - r);
return (a * K_PRIME) >>> -r;
}
I have written this example to show you can do the same thing in BigInteger and why you wouldn't. ;)
public static final BigInteger BI_K_PRIME = new BigInteger("9876534021204356789");
private static long K_PRIME = BI_K_PRIME.longValue();
public static long hash(long a, int r) {
// return (a * K_PRIME % (2^64)) >>> (64 - r);
return (a * K_PRIME) >>> -r;
}
public static long biHash(long a, int r) {
return BigInteger.valueOf(a).multiply(BI_K_PRIME).mod(BigInteger.valueOf(2).pow(64)).shiftRight(64 - r).longValue();
}
public static void main(String... args) {
Random rand = new Random();
for (int i = 0; i < 10000; i++) {
long a = rand.nextLong();
for (int r = 1; r < 64; r++) {
long h1 = hash(a, r);
long h2 = biHash(a, r);
if (h1 != h2)
throw new AssertionError("Expected " + h2 + " but got " + h1);
}
}
int runs = 1000000;
long start1 = System.nanoTime();
for (int i = 0; i < runs; i++)
hash(i, i & 63);
long time1 = System.nanoTime() - start1;
long start2 = System.nanoTime();
for (int i = 0; i < runs; i++)
biHash(i, i & 63);
long time2 = System.nanoTime() - start2;
System.out.printf("hash with long took an average of %,d ns, " +
"hash with BigInteger took an average of %,d ns%n",
time1 / runs, time2 / runs);
}
prints
hash with long took an average of 3 ns, \
hash with BigInteger took an average of 905 ns
Neither int nor long would be sufficiently large enough to hold all of the values you'd need in 2^(w-1). You would be best served with BigInteger.
Let's look what number % 2^32 actually does: It gets the remainder of the division by 2^32. If you have a range from 0 to 2^32, the computer will automatically do the modulo for you, because it throws away everything above 2^32.
Let's take 8 instead of 32, and switch to binary number system:
1000 1000 % 1 0000 0000 = 1000 1000
1 1000 1000 % 1 0000 0000 = 1000 1000
So what you should do is to limit the number to the range of the computer. If you would use e.g. c++, it would be as simple as declaring the value as unsigned int. The first 1 of the second example above would simply be truncated because it does not fit into the variable.
In java, you don't have unsigned integers. If you calculate A * k, and that results in an overflow, you may get a signed value. But as the only thing you have to do next is to do a right shift, this should not matter.
So my suggestion is to simply drop the modulo calculation. Try it, I'm not quite sure whether it works.
The Java primative int has a range of minimum value of -2,147,483,648 and a maximum value of 2,147,483,647
Check out this link for details on the primatives.
I recommend using a long instead of an int.

Categories