(a * b) / c MulDiv and dealing with overflow from intermediate multiplication - java

I need to do the following arithmetic:
long a,b,c;
long result = a*b/c;
While the result is guaranteed to fit in long, the multiplication is not, so it can overflow.
I tried to do it step by step (first multiply and then divide) while dealing with the overflow by splitting the intermediate result of a*b into an int array in size of max 4 ( much like the BigInteger is using its int[] mag variable).
Here I got stuck with the division. I cannot get my head around the bitwise shifts required to do a precise division. All I need is the quotient (don't need the remainder).
The hypothetical method would be:
public static long divide(int[] dividend, long divisor)
Also, I am not considering using BigInteger as this part of the code needs to be fast ( I would like to stick to using primitives and primitive arrays).
Any help would be much appreciated!
Edit:
I am not trying to implement the whole BigInteger myself. What I am trying to do is to solve a specific problem (a*b/c, where a*b can overflow) faster than using the generic BigInteger.
Edit2: It would be ideal if it could be done in a clever way, by not getting overflow at all, some tips surfaced in the comments, but I am still looking for one that is correct.
Update:
I tried to port BigInteger code to my specific needs, without object creation, and in the first iteration, I got ~46% improvement in speed comparing to using BigInteger (on my development pc).
Then I tried a bit modified #David Eisenstat solution, which gave me ~56 % (I ran 100_000_000_000 random inputs from Long.MIN_VALUE to Long.MAX_VALUE) reduced run times(more than 2x) comparing to BigInteger (that is ~18% compared to my adapted BigInteger algo).
There will be more iterations on optimization and testing, but at this point, I think I must accept this answer as the best.

I've been tinkering with an approach that (1) multiplies a and b with the school algorithm on 21-bit limbs (2) proceeds to do long division by c, with an unusual representation of the residual a*b - c*q that uses a double to store the high-order bits and a long to store the low-order bits. I don't know if it can be made to be competitive with standard long division, but for your enjoyment,
public class MulDiv {
public static void main(String[] args) {
java.util.Random r = new java.util.Random();
for (long i = 0; true; i++) {
if (i % 1000000 == 0) {
System.err.println(i);
}
long a = r.nextLong() >> (r.nextInt(8) * 8);
long b = r.nextLong() >> (r.nextInt(8) * 8);
long c = r.nextLong() >> (r.nextInt(8) * 8);
if (c == 0) {
continue;
}
long x = mulDiv(a, b, c);
java.math.BigInteger aa = java.math.BigInteger.valueOf(a);
java.math.BigInteger bb = java.math.BigInteger.valueOf(b);
java.math.BigInteger cc = java.math.BigInteger.valueOf(c);
java.math.BigInteger xx = aa.multiply(bb).divide(cc);
if (java.math.BigInteger.valueOf(xx.longValue()).equals(xx) && x != xx.longValue()) {
System.out.printf("a=%d b=%d c=%d: %d != %s\n", a, b, c, x, xx);
}
}
}
// Returns truncate(a b/c), subject to the precondition that the result is
// defined and can be represented as a long.
private static long mulDiv(long a, long b, long c) {
// Decompose a.
long a2 = a >> 42;
long a10 = a - (a2 << 42);
long a1 = a10 >> 21;
long a0 = a10 - (a1 << 21);
assert a == (((a2 << 21) + a1) << 21) + a0;
// Decompose b.
long b2 = b >> 42;
long b10 = b - (b2 << 42);
long b1 = b10 >> 21;
long b0 = b10 - (b1 << 21);
assert b == (((b2 << 21) + b1) << 21) + b0;
// Compute a b.
long ab4 = a2 * b2;
long ab3 = a2 * b1 + a1 * b2;
long ab2 = a2 * b0 + a1 * b1 + a0 * b2;
long ab1 = a1 * b0 + a0 * b1;
long ab0 = a0 * b0;
// Compute a b/c.
DivBy d = new DivBy(c);
d.shift21Add(ab4);
d.shift21Add(ab3);
d.shift21Add(ab2);
d.shift21Add(ab1);
d.shift21Add(ab0);
return d.getQuotient();
}
}
public strictfp class DivBy {
// Initializes n <- 0.
public DivBy(long d) {
di = d;
df = (double) d;
oneOverD = 1.0 / df;
}
// Updates n <- 2^21 n + i. Assumes |i| <= 3 (2^42).
public void shift21Add(long i) {
// Update the quotient and remainder.
q <<= 21;
ri = (ri << 21) + i;
rf = rf * (double) (1 << 21) + (double) i;
reduce();
}
// Returns truncate(n/d).
public long getQuotient() {
while (rf != (double) ri) {
reduce();
}
// Round toward zero.
if (q > 0) {
if ((di > 0 && ri < 0) || (di < 0 && ri > 0)) {
return q - 1;
}
} else if (q < 0) {
if ((di > 0 && ri > 0) || (di < 0 && ri < 0)) {
return q + 1;
}
}
return q;
}
private void reduce() {
// x is approximately r/d.
long x = Math.round(rf * oneOverD);
q += x;
ri -= di * x;
rf = repairLowOrderBits(rf - df * (double) x, ri);
}
private static double repairLowOrderBits(double f, long i) {
int e = Math.getExponent(f);
if (e < 64) {
return (double) i;
}
long rawBits = Double.doubleToRawLongBits(f);
long lowOrderBits = (rawBits >> 63) ^ (rawBits << (e - 52));
return f + (double) (i - lowOrderBits);
}
private final long di;
private final double df;
private final double oneOverD;
private long q = 0;
private long ri = 0;
private double rf = 0;
}

You can use the greatest common divisor (gcd) to help.
a * b / c = (a / gcd(a,c)) * (b / (c / gcd(a,c)))
Edit: The OP asked me to explain the above equation. Basically, we have:
a = (a / gcd(a,c)) * gcd(a,c)
c = (c / gcd(a,c)) * gcd(a,c)
Let's say x=gcd(a,c) for brevity, and rewrite this.
a*b/c = (a/x) * x * b
--------------
(c/x) * x
Next, we cancel
a*b/c = (a/x) * b
----------
(c/x)
You can take this a step further. Let y = gcd(b, c/x)
a*b/c = (a/x) * (b/y) * y
------------------
((c/x)/y) * y
a*b/c = (a/x) * (b/y)
------------
(c/(xy))
Here's code to get the gcd.
static long gcd(long a, long b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}

David Eisenstat got me thinking some more.
I want simple cases to be fast: let double take care of that.
Newton-Raphson may be a better choice for the rest.
/** Multiplies both <code>factor</code>s
* and divides by <code>divisor</code>.
* #return <code>Long.MIN_VALUE</code> if result out of range,<br/>
* else <code>factorA * factor1 / divisor</code> */
public static long
mulDiv(long factorA, long factor1, long divisor) {
final double dd = divisor,
product = (double)factorA * factor1,
a1_d = product / dd;
if (a1_d < -TOO_LARGE || TOO_LARGE < a1_d)
return tooLarge();
if (-ONE_ < a1_d && a1_d < ONE_)
return 0;
if (-EXACT < product && product < EXACT)
return (long) a1_d;
long pLo = factorA * factor1, //diff,
pHi = high64(factorA, factor1);
if (a1_d < -LONG_MAX_ || LONG_MAX_ < a1_d) {
long maxdHi = divisor >> 1;
if (maxdHi < pHi
|| maxdHi == pHi
&& Long.compareUnsigned((divisor << Long.SIZE-1),
pLo) <= 0)
return tooLarge();
}
final double high_dd = TWO_POWER64/dd;
long quotient = (long) a1_d,
loPP = quotient * divisor,
hiPP = high64(quotient, divisor);
long remHi = pHi - hiPP, // xxx overflow/carry
remLo = pLo - loPP;
if (Long.compareUnsigned(pLo, remLo) < 0)
remHi -= 1;
double fudge = remHi * high_dd;
if (remLo < 0)
fudge += high_dd;
fudge += remLo/dd;
long //fHi = (long)fudge/TWO_POWER64,
fLo = (long) Math.floor(fudge); //*round
quotient += fLo;
loPP = quotient * divisor;
hiPP = high64(quotient, divisor);
remHi = pHi - hiPP; // should be 0?!
remLo = pLo - loPP;
if (Long.compareUnsigned(pLo, remLo) < 0)
remHi -= 1;
if (0 == remHi && 0 <= remLo && remLo < divisor)
return quotient;
fudge = remHi * high_dd;
if (remLo < 0)
fudge += high_dd;
fudge += remLo/dd;
fLo = (long) Math.floor(fudge);
return quotient + fLo;
}
/** max <code>double</code> trusted to represent
* a value in the range of <code>long</code> */
static final double
LONG_MAX_ = Double.valueOf(Long.MAX_VALUE - 0xFFF);
/** max <code>double</code> trusted to represent a value below 1 */
static final double
ONE_ = Double.longBitsToDouble(
Double.doubleToRawLongBits(1) - 4);
/** max <code>double</code> trusted to represent a value exactly */
static final double
EXACT = Long.MAX_VALUE >> 12;
static final double
TWO_POWER64 = Double.valueOf(1L<<32)*Double.valueOf(1L<<32);
static long tooLarge() {
// throw new RuntimeException("result too large for long");
return Long.MIN_VALUE;
}
static final long ONES_32 = ~(~0L << 32);
static long high64(long factorA, long factor1) {
long loA = factorA & ONES_32,
hiA = factorA >>> 32,
lo1 = factor1 & ONES_32,
hi1 = factor1 >>> 32;
return ((loA * lo1 >>> 32)
+loA * hi1 + hiA * lo1 >>> 32)
+ hiA * hi1;
}
(I rearranged this code some out of the IDE to have mulDiv() on top.
Being lazy, I have a wrapper for sign handling - might try and do it properly before hell freezes over.
For timing, a model of input is in dire need:
How about such that each result possible is equally likely?)

Perhaps not clever, but has linear result time
#define MUL_DIV_TYPE unsigned int
#define BITS_PER_TYPE (sizeof(MUL_DIV_TYPE)*8)
#define TOP_BIT_TYPE (1<<(BITS_PER_TYPE-1))
//
// result = ( a * b ) / c, without intermediate overflow.
//
MUL_DIV_TYPE mul_div( MUL_DIV_TYPE a, MUL_DIV_TYPE b, MUL_DIV_TYPE c ) {
MUL_DIV_TYPE st, sb; // product sum top and bottom
MUL_DIV_TYPE d, e; // division result
MUL_DIV_TYPE i, // bit counter
j; // overflow check
st = 0;
sb = 0;
d = 0;
e = 0;
for( i = 0; i < BITS_PER_TYPE; i++ ) {
//
// Shift sum left to make space
// for next partial sum
//
st <<= 1;
if( sb & TOP_BIT_TYPE ) st |= 1;
sb <<= 1;
//
// Add a to s if top bit on b
// is set.
//
if( b & TOP_BIT_TYPE ) {
j = sb;
sb += a;
if( sb < j ) st++;
}
//
// Division.
//
d <<= 1;
if( st >= c ) {
d |= 1;
st -= c;
e++;
}
else {
if( e ) e++;
}
//
// Shift b up by one bit.
//
b <<= 1;
}
//
// Roll in missing bits.
//
for( i = e; i < BITS_PER_TYPE; i++ ) {
//
// Shift across product sum
//
st <<= 1;
if( sb & TOP_BIT_TYPE ) st |= 1;
sb <<= 1;
//
// Division, continued.
//
d <<= 1;
if( st >= c ) {
d |= 1;
st -= c;
}
}
return( d ); // remainder should be in st
}

Divide a/c and b/c into whole and fractional (remainder) parts, then you have:
a*b/c
= c * a/c * b/c
= c * (x/c + y/c) * (z/c + w/c)
= xz/c + xw/c + yz/c + yw/c where x and z are multiples of c
As such, you can trivially calculate the first three factors without overflow. In my experience, this is often enough to cover typical overflow cases. However, if your divisor is too large, such that (a % c) * (b % c) overflows, this method still fails. If that's a typical issue for you, you may want to look at other approaches (e.g. dividing both the biggest of a and b as well as c by 2 until you have no overflows anymore, but how to do that without introducing additional error due to biases in the process is non-trivial -- you'll need to keep a running score of the error in a separate variable, probably)
Anyway, the code for the above:
long a,b,c;
long bMod = (b % c)
long result = a * (b / c) + (a / c) * bMod + ((a % c) * bMod) / c;
If speed is a big concern (I'm assuming it is at least to some extent, since you're asking this), you may want to consider storing a/c and b/c in variables and calculating the mod through multiplication, e.g. replace (a % c) by (a - aDiv * c) -- this allows you to go from 4 divisions per call to 2.

Related

Is n a Ramanujan number--why am I getting errors in values near 2^63?

Given a number, test to see if it is a Ramanujan number (defined in our course as the sum of two cubes two different ways). It must run in n^(1/3) time.
My code is working--sometimes. As test values approach 2^63 -1 I am getting some random errors.
Weirdly, I was passing this test for numbers in that range before I changed the starting value of a counter to fix a different bug. Can anyone tell me why this might be?
I set up a for loop to create values for a^3.
Then I set values for b=(n-a^3)^(1/3).
Then I test b to see if it is an integer. If so, break the loop.
Inserted an if test here to get the code to work, though I have NO IDEA WHY THIS IS NEEDED, and that's the gist of this question. This if statement sets up two different for loops for values above and below n=2^63
Second loop for n < 2^63, starts off with c=a+1 so I don't duplicate. It's the same as the first one.
Second loop for n > 2^63 starts off with c=a.
Why would this make a difference? Why isn't the same code working for smaller and larger numbers?
Sorry for the babyish code, I am just starting out, and a lot of functions are off limits in my course. (For example, I couldn't use floor() and was not allowed to write my own function for it, either).
public class Ramanujan {
public static boolean isRamanujan(long n) {
if (n <= 0) return false;
long a3 = 0;
long c3 = 0;
double b = 0;
double d = 0;
for (int a = 1; a < n; a++) {
a3 = (long) a * a * a;
if (a3 > n) break;
b = Math.cbrt(n - a3);
if (b == (int) b) break;
}
if (n > Math.pow(2, 62)) {
for (int c = (int) Math.cbrt(a3); c < n; c++) {
c3 = (long) c * c * c;
if (c3 > n) break;
d = Math.cbrt(n - c3);
if (d == (int) d) break;
}
}
else {
for (int c = (int) Math.cbrt(a3) + 1; c < n; c++) {
c3 = (long) c * c * c;
if (c3 > n) break;
d = Math.cbrt(n - c3);
if (d == (int) d) break;
}
}
if (a3 + (long) b * b * b == c3 + (long) d * d * d && b * b * b != c3)
return true;
return false;
}
public static void main(String[] args) {
long n = Long.parseLong(args[0]);
StdOut.println(isRamanujan(n));
}
}
Any insight as to why I needed to differentiate between larger and smaller numbers?
You'll get weird results when n exceeds the value a long can hold, i.e. Math.pow(2, 63) == Long.MAX_VALUE. At that point, n will experience a numerical overflow.
final long l = Long.MAX_VALUE; // == 2^63
System.out.println(l); // 9223372036854775807
System.out.println(l + 1); // -9223372036854775808
You get random errors for large int values because of arithmetic overflow when Math.cbrt(a3) or even Math.cbrt(n - a3) exceeds the range of type int. You should use type long for all integer variables to reduce this possibility and make sure intermediary results do not exceed the range of type long.
Here is a simpler implementation using a single loop, computing the number of ways:
public class Ramanujan {
public static boolean isRamanujan(long n) {
if (n <= 0) return false;
int count = 0;
for (long a = 1;; a++) {
long a3 = a * a * a;
if (a3 > n - a3) break;
long b = (long)Math.cbrt(n - a3);
if (a3 + b * b * b == n) count++;
}
return count >= 2;
}
public static void main(String[] args) {
if (args.length == 1) {
long n = Long.parseLong(args[0]);
StdOut.println(isRamanujan(n));
} else
if (args.length == 2) {
long n1 = Long.parseLong(args[0]);
long n2 = Long.parseLong(args[1]);
for (long n = n1; n <= n2; n++) {
if (isRamanujan(n))
StdOut.println(n);
if (n == Long.MAX_VALUE) // handle n2 == Long.MAX_VALUE
break;
}
} else {
StdOut.println("usage: Ramanujan n1 [n2]");
}
}
}
The largest number a long can hold (in Java) is (2 ^ 63) - 1 (Long.MAX_VALUE).
Why are you calculating Math.cbrt(a3) ? If a3 = a * a * a, then you already know what
Math.cbrt(a3) is.
There is a problem in your code if n > 9223372036854774272
Math.cbrt of 9223372036854774273 is 2097152
and if you cube that you get a negative number because of overflow.
The issue is with multiplying variables a and c of type int to calculate the cube. Need to cast each of the variable to long that is being multiplied.
Example, a3 = (long) a * (long) a * (long) a;

What is the most time efficient algorithm/code to reverse a very large integer?

I am trying to get the most efficient algorithm to reverse a large integer in Java.
E.g. if we have to reverse 301324354432.
Till now I have the below code:
public int reverse(int x) {
int result = 0;
while (x != 0)
{
int tail = x % 10;
int newResult = result * 10 + tail;
if ((newResult - tail) / 10 != result)
{ return 0; }
result = newResult;
x = x / 10;
}
return result;
}
What is the correct algorithm to achieve this at best time complexity?
An efficient way is to do it as shown below (similar to what you suggested).
public static long reverse(long x) {
long y = 0;
while(x > 0) {
y = y * 10 + x % 10;
x = x / 10;
}
return y;
}
This avoids expensive string conversions, does only one pass through the digits and does not use any memory (except for storing the result).
EDIT
A more efficient way, avoiding division and modulo operations is:
public static long reverse(int _x) {
long x = _x;
long y = 0;
while (x > 0) {
y = x + (y - ((x * 0x1999999Al) >> 32)) * 10; //y * 10 + x - (x/10) * 10;
x = ((x * 0x1999999Al) >> 32);
}
return y;
}
I also tried replacing multiplication by 10 using bitshift operations (x * 10 = (x << 3) + (x << 1)) but it didn't seem to affect performance.
The top answer of this stackoverflow question shows how to divide fast by 10. For completeness, the answer provided states that it can be done as follows (credit to John Källén)
int32_t div10(int32_t dividend) {
int64_t invDivisor = 0x1999999A;
return (int32_t) ((invDivisor * dividend) >> 32);
}
This approach only allows to reverse an integer number (up to 2^31 - 1). The result is a long, as 2^31 - 1 = 2147483647 and reverse(2147483647) = 7463847412 > 2^31 - 1.
A fast way to perform a modulo 10 operation on x is to divide and multiply it by 10, and then subtract that result from x.
public int reverse(int x) {
int result = 0;
StringBuffer sb = new StringBuffer(0);
sb.append(x);
result = Integer.parseInt(sb.reverse().toString());
return result;
}
You can take advantage of Java lambda expression. All you have to do is convert the number to String, use lambda to reverse it and then convert back to int. A little variation of this code can allow the reversal of any number of characters. Here:
public static int reversal(int x) {
String tmp = String.valueOf( x );
String result = Pattern.compile(" +").splitAsStream( tmp ).map(word->new StringBuilder(word).reverse())
.collect(Collectors.joining(" "));
return Integer.parseInt( result );
}

How to find the floor and remainder of a fraction in Java?

Given integers 'a' and 'b', I would like a method that returns the floor and remainder of a / b such that:
a / b = floor + remainder / |b| (where |b| is the absolute value of b), and
0 <= remainder < |b|.
For example, 5/3 = 1 + 2/3.
Here's an attempt that works only for positive a and b:
public static long[] floorAndRemainder(long a, long b) {
long floor = a / b;
long remainder = a % b;
return new long[] { floor, remainder };
}
I need a function that works for all positive and negative numerators and denominators. For example,
-5/3 = -2 + 1/3
5/-3 = -2 + 1/3
-5/-3 = 1 + 2/3
Implementation 1: Floating Point
Uses floating point math to simplify the logic. Be warned that this will produce incorrect results for large numbers due to loss of precision.
public static long[] floorAndRemainder(long a, long b) {
long floor = (long) Math.floor(a / (double) b);
long remainder = Math.abs(a - floor * b);
return new long[] { floor, remainder };
}
Implementation 2: Find, then Correct
Finds the floor and remainder using integer division and modulus operators, then corrects for negative fractions. This shows that the remainder is relatively difficult to correct without using the floor.
public static long[] floorAndRemainder(long a, long b) {
long floor = a / b;
long remainder = a % b;
boolean isNegative = a < 0 ^ b < 0;
boolean hasRemainder = remainder != 0;
// Correct the floor.
if (isNegative && hasRemainder) {
floor--;
}
// Correct the remainder.
if (hasRemainder) {
if (isNegative) {
if (a < 0) { // then remainder < 0 and b > 0
remainder += b;
} else { // then remainder > 0 and b < 0
remainder = -remainder - b;
}
} else {
if (remainder < 0) {
remainder = -remainder;
}
}
}
return new long[] { floor, remainder };
}
Implementation 3: The Best Option
Finds the floor the same way as Implementation 2, then uses the floor to find the remainder like Implementation 1.
public static long[] floorAndRemainder(long a, long b) {
long floor = a / b;
if ((a < 0 ^ b < 0) && a % b != 0) {
floor--;
}
long remainder = Math.abs(a - floor * b);
return new long[] { floor, remainder };
}

How do i calculate the remainder for extremely large exponential numbers using java?

How do i calculate the remainder for extremely large exponential numbers using java ?
eg. (48^26)/2401
I tried using BIGINTEGER, however it gave the same output for large divisors.I'm not sure if BIG INTEGER can do this .I have tried all other PRIMITIVE data type.They seem to be insufficient.
FYI it tried the following code:
BigInteger a = new BigInteger("48");
a = a.pow(26);
BigInteger b = new BigInteger("2401");//49*49
a = a.mod(b);
System.out.println(a);
I don't know why i got the same output everytime, it's weird that it's working fine now.
The answer comes out to be 1128
You can use repeated modulus of smaller numbers.
say you have
(a * b) % n
((A * n + AA) * (B * n + BB)) % n | AA = a %n & BB = b % n
(A * B * n^2 + A * N * BB + AA * B * n + AA * BB) % n
AA * BB % n since x * n % n == 0
(a % n) * (b % n) % n
In your case, you can write
48^26 % 2401
(48^2) ^ 13 % 2401
as
int n = 48;
for (int i = 1; i < 26; i++)
n = (n * 48) % 2401;
System.out.println(n);
int n2 = 48 * 48;
for (int i = 1; i < 13; i++)
n2 = (n2 * 48 * 48) % 2401;
System.out.println(n2);
System.out.println(BigInteger.valueOf(48).pow(26).mod(BigInteger.valueOf(2401)));
prints
1128
1128
1128
As #Ruchina points out, your example is small enough to calculate using a simple double expression.
for (int i = 1; i < 100; i++) {
BigInteger mod = BigInteger.valueOf(48).pow(i).mod(BigInteger.valueOf(2401));
double x = Math.pow(48, i) % 2401;
if (mod.intValue() != x) {
System.out.println(i + ": " + mod + " vs " + x);
break;
}
}
prints
34: 736 vs 839.0
In other words, any power of 48 is fine up to 33.
This worked for me.
import java.math.BigInteger;
public class BigMod{
public static void main (String[] args){
BigInteger b1 = new BigInteger ("48");
BigInteger b2 = new BigInteger ("2401");
BigInteger b3 = b1.pow(26);
BigInteger result = b3.mod(b2);
System.out.println(result);
}
}
Not sure what trouble you're having with BigInteger. Can you explain what didn't work?
Use BigInteger.modPow().
BigInteger a = new BigInteger("48");
BigInteger b = new BigInteger("26");
BigInteger c = new BigInteger("2401");
BigInteger answer = a.modPow(b, c);
The answer will be 1128. Note that BigInteger is immutable so objects a, b, and c can not be modified.
You don't even need a BigInteger for this, you can calculate that value using BigMod divide and conquer algorithm taking advantage of the following property of the mod operation
(A * B) mod n = ((A mod n) * (B mod n)) mod n
Then (B ^ c) mod n can be viewed as a special case of the property:
(B ^ c) mod n = ((B mod n) * (B mod n) ... c times) mod n
The following code does the calculation:
public class BigModExample {
public static long bigMod(long b, long c, int n) {
if (c == 0) {
return 1;
}
// Returns: (b ^ c/2) mod n
long b2 = bigMod(b, c / 2, n);
// Even exponent
if ((c & 1) == 0) {
// [((b ^ c/2) mod n) * ((b ^ c/2) mod n)] mod n
return (b2 * b2) % n;
} else {
// Odd exponent
// [(b mod n) * ((b ^ c/2) mod n) * ((b ^ c/2) mod n)] mod n
return ((b % n) * (b2 * b2)) % n;
}
}
public static void main(String... args) {
System.out.println(bigMod(48, 26, 2401));
}
}
Prints
1128
Further explanation on Peter Lawrey's solution.
(a*b)%n
= ((A*n + AA) * (B*n + BB))%n where a=A*n+AA, AA=a%n & b=B*n+BB, BB=b%n
= (A*B*n^2 + A*n*BB + AA*B*n + AA*BB)%n
= (AA*BB)%n
= (a%n * b%n)%n
(a^c)%n
= (a^(c-1) * a)%n
= ((a^(c-1))%n * a%n)%n
= ((a^(c-2)*a)%n * a%n)%n
= ((a^(c-2)%n * a%n)%n * a%n)%n
Example1: when c is 3
(a^3)%n
= ((a^2)*a)%n
= ((a^2)%n * a%n)%n
= ((a*a)%n * a%n)%n
= ((a%n * a%n)%n * a%n)%n
Example2: when c is 4
(a^4)%n
= ((a^3)*a)%n
= ((a^3)%n * a%n)%n
= ((a^2 * a)%n * a%n)%n
= (((a^2)%n * a%n)%n * a%n)%n
= (((a*a)%n * a%n)%n * a%n)%n
= ((a%n * a%n)%n * a%n)%n * a%n)%n
java code:
int a = 48;
int c = 26;
int n = 2401;
int a_mod_n = a%n;
int result = a_mod_n;
for (int i = 1; i < c; i++) {
result = (result * a_mod_n) % n;
}
System.out.println("result: " + result);
48 is ambiguous as both a and a%n are 48.
The above Java code strictly follows the equation ((a^(c-2)%n * a%n)%n * a%n)%n so that it is easier to understand.
BigDecimal b= BigDecimal.valueOf(Math.pow(48,26) %2401);
output b = 1128.0
Try using a BigDecimal for large decimal numbers. It is not prone to errors like double and float because of the way it's data is stored. Also, it has a (potentially) infinite amount of decimal places.

How can I perform multiplication without the '*' operator?

I was just going through some basic stuff as I am learning C. I came upon a question to multiply a number by 7 without using the * operator. Basically it's like this
(x << 3) - x;
Now I know about basic bit manipulation operations, but I can't get how do you multiply a number by any other odd number without using the * operator? Is there a general algorithm for this?
Think about how you multiply in decimal using pencil and paper:
12
x 26
----
72
24
----
312
What does multiplication look like in binary?
0111
x 0101
-------
0111
0000
0111
-------
100011
Notice anything? Unlike multiplication in decimal, where you need to memorize the "times table," when multiplying in binary, you are always multiplying one of the terms by either 0 or 1 before writing it down in the list addends. There's no times table needed. If the digit of the second term is 1, you add in the first term. If it's 0, you don't. Also note how the addends are progressively shifted over to the left.
If you're unsure of this, do a few binary multiplications on paper. When you're done, convert the result back to decimal and see if it's correct. After you've done a few, I think you'll get the idea how binary multiplication can be implemented using shifts and adds.
Everyone is overlooking the obvious. No multiplication is involved:
10^(log10(A) + log10(B))
The question says:
multiply a number by 7 without using * operator
This doesn't use *:
number / (1 / 7)
Edit:
This compiles and works fine in C:
int number,result;
number = 8;
result = number / (1. / 7);
printf("result is %d\n",result);
An integer left shift is multiplying by 2, provided it doesn't overflow. Just add or subtract as appropriate once you get close.
int multiply(int multiplicand, int factor)
{
if (factor == 0) return 0;
int product = multiplicand;
for (int ii = 1; ii < abs(factor); ++ii) {
product += multiplicand;
}
return factor >= 0 ? product : -product;
}
You wanted multiplication without *, you got it, pal!
It's easy to avoid the '*' operator:
mov eax, 1234h
mov edx, 5678h
imul edx
No '*' in sight. Of course, if you wanted to get into the spirit of it, you could also use the trusty old shift and add algorithm:
mult proc
; Multiplies eax by ebx and places result in edx:ecx
xor ecx, ecx
xor edx, edx
mul1:
test ebx, 1
jz mul2
add ecx, eax
adc edx, 0
mul2:
shr ebx, 1
shl eax, 1
test ebx, ebx
jnz mul1
done:
ret
mult endp
Of course, with modern processors, all (?) have multiplication instructions, but back when the PDP-11 was shiny and new, code like this saw real use.
Mathematically speaking, multiplication distributes over addition. Essentially, this means:
x * (a + b + c ...) = (x * a) + (x * b) + (x * c) ...
Any real number (in your case 7), can be presented as a series of additions (such as 8 + (-1), since subtraction is really just addition going the wrong way). This allows you to represent any single multiplication statement as an equivalent series of multiplication statements, which will come up with the same result:
x * 7
= x * (8 + (-1))
= (x * 8) + (x * (-1))
= (x * 8) - (x * 1)
= (x * 8) - x
The bitwise shift operator essentially just multiplies or divides a number by a power of 2. So long as your equation is only dealing with such values, bit shifting can be used to replace all occurrence of the multiplication operator.
(x * 8) - x = (x * 23) - x = (x << 3) - x
A similar strategy can be used on any other integer, and it makes no difference whether it's odd or even.
It is the same as x*8-x = x*(8-1) = x*7
Any number, odd or even, can be expressed as a sum of powers of two. For example,
1 2 4 8
------------------
1 = 1
2 = 0 + 2
3 = 1 + 2
4 = 0 + 0 + 4
5 = 1 + 0 + 4
6 = 0 + 2 + 4
7 = 1 + 2 + 4
8 = 0 + 0 + 0 + 8
11 = 1 + 2 + 0 + 8
So, you can multiply x by any number by performing the right set of shifts and adds.
1x = x
2x = 0 + x<<1
3x = x + x<<1
4x = 0 + 0 + x<<2
5x = x + 0 + x<<2
11x = x + x<<1 + 0 + x<<3
When it comes down to it, multiplication by a positive integer can be done like this:
int multiply(int a, int b) {
int ret = 0;
for (int i=0; i<b; i++) {
ret += b;
}
return ret;
}
Efficient? Hardly. But it's correct (factoring in limits on ints and so forth).
So using a left-shift is just a shortcut for multiplying by 2. But once you get to the highest power-of-2 under b you just add a the necessary number of times, so:
int multiply(int a, int b) {
int ret = a;
int mult = 1;
while (mult <= b) {
ret <<= 1;
mult <<= 1;
}
while (mult < b) {
ret += a;
}
return ret;
}
or something close to that.
To put it another way, to multiply by 7.
Left shift by 2 (times 4). Left shift 3 is 8 which is >7;
Add b 3 times.
One evening, I found that I was extremely bored, and cooked this up:
#include <iostream>
typedef unsigned int uint32;
uint32 add(uint32 a, uint32 b) {
do {
uint32 s = a ^ b;
uint32 c = a & b;
a = s;
b = c << 1;
} while (a & b)
return (a | b)
}
uint32 mul(uint32 a, uint32 b) {
uint32 total = 0;
do {
uint32 s1 = a & (-(b & 1))
b >>= 1; a <<= 1;
total = add(s1, total)
} while (b)
return total;
}
int main(void) {
using namespace std;
uint32 a, b;
cout << "Enter two numbers to be multiplied: ";
cin >> a >> b;
cout << "Total: " << mul(a,b) << endl;
return 0;
}
The code above should be quite self-explanatory, as I tried to keep it as simple as possible. It should work, more or less, the way a CPU might perform these operations. The only bug I'm aware of is that a is not permitted to be greater than 32,767 and b is not permitted to be large enough to overflow a (that is, multiply overflow is not handled, so 64-bit results are not possible). It should even work with negative numbers, provided the inputs are appropriately reinterpret_cast<>.
O(log(b)) method
public int multiply_optimal(int a, int b) {
if (a == 0 || b == 0)
return 0;
if (b == 1)
return a;
if ((b & 1) == 0)
return multiply_optimal(a + a, b >> 1);
else
return a + multiply_optimal(a + a, b >> 1);
}
The resursive code works as follows:
Base case:
if either of the number is 0 ,product is 0.
if b=1, product =a.
If b is even:
ab can be written as 2a(b/2)
2a(b/2)=(a+a)(b/2)=(a+a)(b>>1) where'>>' arithematic right shift operator in java.
If b is odd:
ab can be written as a+a(b-1)
a+a(b-1)=a+2a(b-1)/2=a+(a+a)(b-1)/2=a+(a+a)((b-1)>>1)
Since b is odd (b-1)/2=b/2=b>>1
So ab=a+(2a*(b>>1))
NOTE:each recursive call b is halved => O(log(b))
unsigned int Multiply(unsigned int m1, unsigned int m2)
{
unsigned int numBits = sizeof(unsigned int) * 8; // Not part of the core algorithm
unsigned int product = 0;
unsigned int mask = 1;
for(int i =0; i < numBits; ++i, mask = mask << 1)
{
if(m1 & mask)
{
product += (m2 << i);
}
}
return product;
}
#Wang, that's a good generalization. But here is a slightly faster version. But it assumes no overflow and a is non-negative.
int mult(int a, int b){
int p=1;
int rv=0;
for(int i=0; a >= p && i < 31; i++){
if(a & p){
rv += b;
}
p = p << 1;
b = b << 1;
}
return rv;
}
It will loop at most 1+log_2(a) times. Could be faster if you swap a and b when a > b.
import java.math.BigInteger;
public class MultiplyTest {
public static void main(String[] args) {
BigInteger bigInt1 = new BigInteger("5");
BigInteger bigInt2 = new BigInteger("8");
System.out.println(bigInt1.multiply(bigInt2));
}
}
Shift and add doesn't work (even with sign extension) when the multiplicand is negative. Signed multiplication has to be done using Booth encoding:
Starting from the LSB, a change from 0 to 1 is -1; a change from 1 to 0 is 1, otherwise 0. There is also an implicit extra bit 0 below the LSB.
For example, the number 5 (0101) will be encoded as: (1)(-1)(1)(-1). You can verify this is correct:
5 = 2^3 - 2^2 + 2 -1
This algorithm also works with negative numbers in 2's complement form:
-1 in 4-bit 2's complement is 1111. Using the Booth algorithm: (1)(0)(0)(0)(-1), where there is no space for the leftmost bit 1 so we get: (0)(0)(0)(-1) which is -1.
/* Multiply two signed integers using the Booth algorithm */
int booth(int x, int y)
{
int prev_bit = 0;
int result = 0;
while (x != 0) {
int current_bit = x & 0x1;
if (prev_bit & ~current_bit) {
result += y;
} else if (~prev_bit & current_bit) {
result -= y;
}
prev_bit = current_bit;
x = static_cast<unsigned>(x) >> 1;
y <<= 1;
}
if (prev_bit)
result += y;
return result;
}
The above code does not check for overflow. Below is a slightly modified version that multiplies two 16 bit numbers and returns a 32 bit number so it never overflows:
/* Multiply two 16-bit signed integers using the Booth algorithm */
/* Returns a 32-bit signed integer */
int32_t booth(int16_t x, int16_t y)
{
int16_t prev_bit = 0;
int16_t sign_bit = (x >> 16) & 0x1;
int32_t result = 0;
int32_t y1 = static_cast<int32_t>(y);
while (x != 0) {
int16_t current_bit = x & 0x1;
if (prev_bit & ~current_bit) {
result += y1;
} else if (~prev_bit & current_bit) {
result -= y1;
}
prev_bit = current_bit;
x = static_cast<uint16_t>(x) >> 1;
y1 <<= 1;
}
if (prev_bit & ~sign_bit)
result += y1;
return result;
}
unsigned int Multiply( unsigned int a, unsigned int b )
{
int ret = 0;
// For each bit in b
for (int i=0; i<32; i++) {
// If that bit is not equal to zero
if (( b & (1 << i)) != 0) {
// Add it to our return value
ret += a << i;
}
}
return ret;
}
I avoided the sign bit, because it's kind of not the subject of the post. This is an implementation of what Wayne Conrad said basically. Here is another problem is you want to try more low level math operations. Project Euler is cool!
If you can use the log function:
public static final long multiplyUsingShift(int a, int b) {
int absA = Math.abs(a);
int absB = Math.abs(b);
//Find the 2^b which is larger than "a" which turns out to be the
//ceiling of (Log base 2 of b) == numbers of digits to shift
double logBase2 = Math.log(absB) / Math.log(2);
long bits = (long)Math.ceil(logBase2);
//Get the value of 2^bits
long biggerInteger = (int)Math.pow(2, bits);
//Find the difference of the bigger integer and "b"
long difference = biggerInteger - absB;
//Shift "bits" places to the left
long result = absA<<bits;
//Subtract the "difference" "a" times
int diffLoop = Math.abs(a);
while (diffLoop>0) {
result -= difference;
diffLoop--;
}
return (a>0&&b>0 || a<0&&b<0)?result:-result;
}
If you cannot use the log function:
public static final long multiplyUsingShift(int a, int b) {
int absA = Math.abs(a);
int absB = Math.abs(b);
//Get the number of bits for a 2^(b+1) larger number
int bits = 0;
int bitInteger = absB;
while (bitInteger>0) {
bitInteger /= 2;
bits++;
}
//Get the value of 2^bit
long biggerInteger = (int)Math.pow(2, bits);
//Find the difference of the bigger integer and "b"
long difference = biggerInteger - absB;
//Shift "bits" places to the left
long result = absA<<bits;
//Subtract the "difference" "a" times
int diffLoop = absA;
while (diffLoop>0) {
result -= difference;
diffLoop--;
}
return (a>0&&b>0 || a<0&&b<0)?result:-result;
}
I found this to be more efficient:
public static final long multiplyUsingShift(int a, int b) {
int absA = Math.abs(a);
int absB = Math.abs(b);
long result = 0L;
while (absA>0) {
if ((absA&1)>0) result += absB; //Is odd
absA >>= 1;
absB <<= 1;
}
return (a>0&&b>0 || a<0&&b<0)?result:-result;
}
and yet another way.
public static final long multiplyUsingLogs(int a, int b) {
int absA = Math.abs(a);
int absB = Math.abs(b);
long result = Math.round(Math.pow(10, (Math.log10(absA)+Math.log10(absB))));
return (a>0&&b>0 || a<0&&b<0)?result:-result;
}
In C#:
private static string Multi(int a, int b)
{
if (a == 0 || b == 0)
return "0";
bool isnegative = false;
if (a < 0 || b < 0)
{
isnegative = true;
a = Math.Abs(a);
b = Math.Abs(b);
}
int sum = 0;
if (a > b)
{
for (int i = 1; i <= b; i++)
{
sum += a;
}
}
else
{
for (int i = 1; i <= a; i++)
{
sum += b;
}
}
if (isnegative == true)
return "-" + sum.ToString();
else
return sum.ToString();
}
JAVA:Considering the fact, that every number can be splitted into powers of two:
1 = 2 ^ 0
2 = 2 ^ 1
3 = 2 ^ 1 + 2 ^ 0
...
We want to get x where:
x = n * m
So we can achieve that by doing following steps:
1. while m is greater or equal to 2^pow:
1.1 get the biggest number pow, such as 2^pow is lower or equal to m
1.2 multiply n*2^pow and decrease m to m-2^pow
2. sum the results
Sample implementation using recursion:
long multiply(int n, int m) {
int pow = 0;
while (m >= (1 << ++pow)) ;
pow--;
if (m == 1 << pow) return (n << pow);
return (n << pow) + multiply(n, m - (1 << pow));
}
I got this question in last job interview and this answer was accepted.
EDIT: solution for positive numbers
This is the simplest C99/C11 solution for positive numbers:
unsigned multiply(unsigned x, unsigned y) { return sizeof(char[x][y]); }
Another thinking-outside-the-box answer:
BigDecimal a = new BigDecimal(123);
BigDecimal b = new BigDecimal(2);
BigDecimal result = a.multiply(b);
System.out.println(result.intValue());
public static int multiply(int a, int b)
{
int temp = 0;
if (b == 0) return 0;
for (int ii = 0; ii < abs(b); ++ii) {
temp = temp + a;
}
return b >= 0 ? temp : -temp;
}
public static int abs(int val) {
return val>=0 ? val : -val;
}
public static void main(String[] args) {
System.out.print("Enter value of A -> ");
Scanner s=new Scanner(System.in);
double j=s.nextInt();
System.out.print("Enter value of B -> ");
Scanner p=new Scanner(System.in);
double k=p.nextInt();
double m=(1/k);
double l=(j/m);
System.out.print("Multiplication of A & B=> "+l);
}
package com.amit.string;
// Here I am passing two values, 7 and 3 and method getResult() will
// return 21 without use of any operator except the increment operator, ++.
//
public class MultiplyTwoNumber {
public static void main(String[] args) {
int a = 7;
int b = 3;
System.out.println(new MultiplyTwoNumber().getResult(a, b));
}
public int getResult(int i, int j) {
int result = 0;
// Check for loop logic it is key thing it will go 21 times
for (int k = 0; k < i; k++) {
for (int p = 0; p < j; p++) {
result++;
}
}
return result;
}
}
Loop it. Run a loop seven times and iterate by the number you are multiplying with seven.
Pseudocode:
total = 0
multiply = 34
loop while i < 7
total = total + multiply
endloop
A JavaScript approach for positive numbers
function recursiveMultiply(num1, num2){
const bigger = num1 > num2 ? num1 : num2;
const smaller = num1 <= num2 ? num1 : num2;
const indexIncrement = 1;
const resultIncrement = bigger;
return recursiveMultiplyHelper(bigger, smaller, 0, indexIncrement, resultIncrement)
}
function recursiveMultiplyHelper(num1, num2, index, indexIncrement, resultIncrement){
let result = 0;
if (index === num2){
return result;
}
if ((index+indexIncrement+indexIncrement) >= num2){
indexIncrement = 1;
resultIncrement = num1;
} else{
indexIncrement += indexIncrement;
resultIncrement += resultIncrement;
}
result = recursiveMultiplyHelper(num1, num2, (index+indexIncrement), indexIncrement, resultIncrement);
result += resultIncrement;
console.log(num1, num2, index, result);
return result;
}
Think about the normal multiplication method we use
1101 x =>13
0101 =>5
---------------------
1101
0000
1101
0000
===================
1000001 . => 65
Writing the same above in the code
#include<stdio.h>
int multiply(int a, int b){
int res = 0,count =0;
while(b>0) {
if(b & 0x1)
res = res + (a << count);
b = b>>1;
count++;
}
return res;
}
int main() {
printf("Sum of x+y = %d", multiply(5,10));
return 0;
}
Very simple, pal... Each time when you left shift a number it means you are multiplying the number by 2 which means the answer is (x<<3)-x.
To multiply of two numbers without * operator:
int mul(int a,int b) {
int result = 0;
if(b > 0) {
for(int i=1;i<=b;i++){
result += a;
}
}
return result;
}

Categories

Resources