Calculate power with very big exponents in java - java

I have a problem in calculating the power of very big exponent. That is: i enter my password :"abc" then calculate x=Hash(password). after that, i have to calculate Y = pow(g,x) in which, g is a random number. So how can i calculate Y. Any suggestion ? thank you very much !

In cryptography c = m^e (mod n) where c is the cipher text, n is your max value that can be represented. Modulus operation is needed.
In addition to that, for large numbers exponentiation Exponentiation by squaring is used. pow operation implements this algorithm. Code is here.
Cryptography implementation is much more complex, through, predefined byte arrays and byte operations. You can refer to this paper's, Modular Exponentiation and Roots section.

For your purpose, you may want to look into BigInteger.modPow() method, more relevant than Math.pow() method.
http://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html

The problem is that 10^100 is 100 digits. If your hash, lets say 4 billions, resulting value would consume 4Gb of memory. So your problem is barely solvable on a modern hardware.
Are you sure Y is pow(g,x) and not pow(g,x) mod SOME_VALUE? Then it'll make more sense.

Related

Java BigInteger pow with BigInteger exponent

Hi i want to calculate
2^(256bit number)
in java, but biginteger's pow function just can handle ints.
How can i calculate with larger numbers?
Is there any library?
i want to calculate all numbers from
2^0
2^1
2^2
...
2^(10^77)
I suspect the reason they didn't bother including anything like this is that in most cases, the number would be too big to represent.
Consider 2^(256 bit number). The result has (256bit number) bits, meaning that it takes more memory then there are particles in the universe.
So you'll have to find a different way to represent your logic. Perhaps you could do it symbolically.
It would be possible to do 2^(2^32) and exponents close to that, but this was probably seen as a niche case that they just didn't bother adding a function for.

How to actually avoid floating point errors when you need to use float?

I am trying to affect the translation of a 3D model using some UI buttons to shift the position by 0.1 or -0.1.
My model position is a three dimensional float so simply adding 0.1f to one of the values causes obvious rounding errors. While I can use something like BigDecimal to retain precision, I still have to convert it from a float and back to a float at the end and it always results in silly numbers that are making my UI look like a mess.
I could just pretty the displayed values but the rounding errors will only get worse with more editing and they make my save files rather hard to read.
So how do I actually avoid these errors when I need to use a float?
The Kahan summation and pairwise summation algorithms help to reduce floating point errors. Here's some Java code for the Kahan algorithm.
I would use a Rational class. There are many out there - this one looks like it should work.
One significant cost will be when the Rational is rendered into a float and one when the denominator is reduced to the gcd. The one I posted keeps the numerator and denominator in fully reduced state at all times which should be quite efficient if you are always adding or subtracting 1/10.
This implementation holds the values normalised (i.e. with consistent sign) but unreduced.
You should choose your implementation to best fit your usage.
A simple solution is to either use fixed precision. i.e. an integer 10x or 100x what you want.
float f = 10;
f += 0.1f;
becomes
int i = 100;
i += 1; // use an many times as you like
// use i / 10.0 as required.
I wouldn't use float in any case as you get more rounding errors than double for next to no benefit (unless you have millions of float values) double gives you 8 more digits of precision and with sensible rounding would won't see those errors.
If you stick with floats:
The easiest way to avoid the error is using floats which are exact, but
near the desired value which is
round(2^n * value) * 1/2^n.
n is the number of bits, value the number to use (in your case 0.1)
In your case with increasing precision:
n = 4 => 0.125
n = 8 (byte) => 0.9765625
n = 16 (short)=> 0.100006103516....
The long number chains are artefacts of the binary conversion,
the real number has much less bits.
As the floats are exact, addition and subtraction will
not introduce offset errors, but will always be
predictable as long as the number of bits is
not longer than the float value holds.
If you fear that your display will be compromised by
using this solution (because they are odd floats), use
and store only integers (step increase -1/1).
The final value which is internally set is
x = value * step.
As the step increases or decreases by an amount of 1,
precision will be retained.

Nan from maths equation

Hi I have the following equation in a piece of java code:
double z = 0.002378 * (Math.pow((1 - (Math.pow(6.875, -6) * y)), 4.2561));
when I set y to be very large values, i.e 200000 I get Nan (Not a number) It's working okay at slightly lower values, 130000
Can anyone tell me why that is?
Additionally I've tried to port the above code from an original BASIC program:
.002378*(1-(6.875*10^-6*ALT))^4.2561
I may have done it wrong? The order of operations isn't very explicit in the BASIC code
Thanks
As the Javadoc for Math.pow explains:
If the first argument is finite and less than zero [… and] the second argument is finite and not an integer, then the result is NaN.
So whenever your y is great enough that 1 - (Math.pow(6.875, -6) * y is negative, you'll get NaN.
(This makes sense when you consider the underlying math. A negative number to a non-integer power is not a real number, and double has no way to represent complex numbers.)
Edited for updated question:
Your Basic code has 6.875*10^-6 (meaning 6.875 × 10−6), but your Java code has Math.pow(6.875, -6) (meaning 6.875−6), which is a somewhat greater value, so your Java code triggers this problem for somewhat smaller values of y. This may be why you're seeing this problem now. To match the Basic code, you should change Math.pow(6.875, -6) to 6.875e-6.
Raising a negative number to a non-integer power results in an imaginary number in complex number mathematics, a NaN in Java arithmetic. If you really need to do that calculation, you need a complex number package. However, it is more likely that there is an error in your equation or you are trying to use it outside its range of validity.
Negtive number with real number power may get NAN

Avoiding arithmetic overflow

Assume you have 2 positive long values a and b which are greater than 2^32 (and smaller than 2^63), and an long integer c.
What is the best way, in java and\or c, to perform operations such as
(a*b)%c
while avoiding arithmetic overflow.
Edit :
c is around 2^34, and sometimes both a and b are just between 2^32 and c...
I finally avoided using BigInteger for the specific situation I was in. Indeed, It was possible to know one divisor of both a and b (not always the case), so I would use the arithmetic properties of modulo to my advantage.
Assuming everything's positive, then you can use the following mathematical identity:
(a*b)%c == ((a%c) * (b%c)) % c
Of course, this still doesn't eliminate the possibility of overflow.
The easiest way to completely avoid the issue is to use a big-integer library.
You can go even further than what #Oli Charlesworth suggests in his (good) answer. You can decompose in factors a and b (not necessary in all the prime factors, a partial decomposition might be enough) and perform the modulus in any intermediate result of the multiplication. Although this is likely to be more costly than going for the bignum, as it will involve quite a few divisions and they are expensive.
In Java I would use BigInteger:
BigInteger bd = BigInteger.valueOf(2).pow(33);
System.out.println(bd.multiply(bd).remainder(BigInteger.valueOf(2).pow(34).add(BigInteger.valueOf(1))));
To the best of my knowledge, there's no way to solve your problem without higher precision arithmetics, and at least LLVM's optimizer agrees.
If 128-bit math is not available natively, you'll need to use a general-purpose big integer library, or take the bits you need from a less general implementation like Math128 from GnuCash.

Using logarithm instead of division for large numbers?

I couldn't really come up with a proper title for my question but allow me to present my case; I want to calculate a significance ratio in the form: p = 1 - X / Y
Here X comes from an iterative process; the process takes a large number of steps and counts how many different ways the process can end up in different states (stored in a HashMap). Once the iteration is over, I select a number of states and sum their values. It's hard to tell how large these numbers are so I am intending to implement the sum as BigInteger.
Y, on the other hand comes from a binomial coefficient with numbers in thousands-scale. I am inclined to use logGamma to calculate these coefficients, which as a result give me the natural logarithm of the value.
What I am interested in is to do division X / Y in the best/most effective way. If I can get X in the natural logarithm then I could subtract the powers and have my result as 1 - e ^ (lnX - lnY).
I see that BigInteger can't be logarithmized by Math.log, what can I do in this case?
You may be able to use doubles. A double can be extremely large, about 1.7e308. What it lacks is precision: it only supports about 15 digits. But if you can live with 15 digits of precision (in other words, if you don't care about the difference between 1,000,000,000,000,000 and 1,000,000,000,000,001) then doubles might get you close enough.
If you are calculating binomial coefficients on numbers in the thousands, then Doubles will not be good enough.
Instead I would be inclined to call the toString method on the number, and compute the log as log(10) * number.toString().length() + log(asFloat("0." + number.toString()) where asFloat takes a string representation of a number and converts it to a float.
If you need maximum precision, how about converting the BigIntegers into BigDecimals and doing algebra on them. If precision isn't paramount, then perhaps you can convert your BigIntegers into doubles and do simple algebra with them. Perhaps you can tell us more about your problem domain and why you feel logarithms are the best way to go.

Categories