log2 for BigInteger in Java - java

Wondering if there is an API to calculate log_2 directly? Here is my current code, which I transfer log_2(N) to be log_e(N)/log_e(2).
BTW, it seems for normal Java Double type, there is no method to calculate log_2(double_value) directly?
My code in Java,
BigInteger x = BigInteger.valueOf(16);
BigInteger y = BigInteger.valueOf((long)(Math.log(x.longValue()) / Math.log(2)));
System.out.println(y.doubleValue()); // return 4.0 as expected

This is built in to the BigInteger API. From the Javadoc:
public int bitLength()
Returns the number of bits in the minimal two's-complement representation of this BigInteger, excluding a sign bit. For positive BigIntegers, this is equivalent to the number of bits in the ordinary binary representation. (Computes (ceil(log2(this < 0 ? -this : this+1))).)

If you want partial bits:
const twoToThe50th = Math.pow(2, 50);
const log2BigInt = (x: bigint) => {
let log = 0;
while (x > twoToThe50th) {
// Shift by 6 bytes to right to stay on byte boundaries
x = x >> BigInt(48);
log += 48;
}
// x is now small enough to be a Number, which we
// can pass to JavaScript's built in log2 function
return log + Math.log2(Number(x));
}

Related

How to do unsigned integer left shift bit operation in Java 1.8 that matches C#?

I'm trying to port some code from C# to Java and I'm stuck on some low-level bit operations.
Here is an example snippet that I'm trying to figure out how to translate from C# to Java:
int shiftAmount = 2;
uint[] tbl = { 1023326899, 1265601397, 3234840308, 1673932182 };
uint[] tblShift = new uint[4];
for (int x = 0; x < tbl.Length; ++x)
{
tblShift[x] = tbl[x] << shiftAmount;
Console.WriteLine(tblShift[x]);
}
Result:
[0] 4093307596 uint
[1] 767438292 uint
[2] 54459344 uint
[3] 2400761432 uint
So far so good.
How do you convert this same thing to Java?
So in Java, I naively just tried turning all the uint to long, it's not correct for all the values:
long[] tbl = { 1023326899L, 1265601397L, 3234840308L, 1673932182L };
long[] tblShift = new long[4];
for (int x = 0; x < tbl.length; ++x) {
tblShift[x] = tbl[x] << shiftAmount;
}
You get:
0 = 4093307596
1 = 5062405588
2 = 12939361232
3 = 6695728728
I'm guessing I have to make an additional shift operation to account for the extra bits in the long integer. And probably also have to account for the signed-ness of the integer as well when doing bit operations. But everything I've tried seems to come up wrong.
Does anyone have a guide on how to translate common C++/C# unsigned integer operations to work in Java?
UPDATE: I found a library on Maven central https://github.com/jOOQ/jOOU and it does have some nice unsigned int support, but lacks the bitwise operation libraries. Perhaps I should keep digging looking for an unsigned-bit-operation library.
The reason is that long in Java can hold a larger number than uint in C# can. uint is limited to 4,294,967,295 (0xFFFFFFFF) whereas Java's long can hold up to 9,223,372,036,854,775,807.
Taking your example of 1265601397L << 2:
The C# result is 767438292
The Java result is 5062405588 (0x12DBE2DD4)
If we use a mask of 0xFFFFFFFF, then we get 0x2DBE2DD4, which equals 767438292
Therefore the solution is to use the bitwise AND operator (&) to apply the mask and get the C# int-equivalent value:
int shiftAmount = 2;
long[] tbl = { 1023326899L, 1265601397L, 3234840308L, 1673932182L };
long[] tblShift = new long[4];
for (int x = 0; x < tbl.length; ++x) {
tblShift[x] = (tbl[x] << shiftAmount) & 0xFFFFFFFFL;
}
Try it online (Java)
Fiddle of your C# code
Results:
Input
C# output
Java output
1023326899
4093307596
4093307596
1265601397
767438292
767438292
3234840308
54459344
54459344
1673932182
2400761432
2400761432

How to convert the var in js into java?

Now I'm try to convert some js code into java , there is a problem:
In js
46022*65535 = 3016051770
and
(46022*65535)|7867 = -1278910789
In java
46022*65535 = -1278915526 this is overflow
46022L*65535L = 3016051770L this is the same result to js
(46022*65535)|7867 = -1278910789 this one and the one below is the problem
(46022L*65535L)|7867L = 3016056507L
So , why the | operator will make two positive number to be nagtive number?
What's the different between java and js when dealing with the int and long to do this operation?
And then , how to write java code compatible with js in this situation ?
Attention:I know the range of int and long , my problem is |.
More problems :
According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
& is also 32bit operation, then:
In js
2996101485 & 65535 = 57709
In java
2996101485 is overflow to int so I use double to store it and cast it into int when I need to do AND.
double a = 2996101485l;
double b = 65535;
int c = (int) a & (int) b; Now c = 65535
But if I use long to cast :
long c = (long) a & (long) b; Now c = 57709
So , just simply cast double into int will cause problems. And I want to know why?
I got the problem , 2996101485 can be present in 32bit in js and in java it should be long. So I write functions to convert those operations , for example, & should use this java function to run give same result in js:
private double doOR(double x, double y) {
if (x > Integer.MAX_VALUE && x <= 1l << 32) {
if (y > Integer.MAX_VALUE && y <= 1l << 32) {
return (long) x | (long) y;
} else {
return (long) x | (int) y;
}
} else {
return (int) x | (int) y;
}
}
The problem is that while numbers in JavaScript have roughly 53-bit precision (they appear to be based on floating point doubles), the bitwise OR operates on only 32 bits.
Bitwise operators treat their operands as a sequence of 32 bits (zeroes and ones), rather than as decimal, hexadecimal, or octal numbers.
This means that when working with arithmetic, long will get you the JavaScript-like arithmetic (with numbers such as yours), since Java ints will overflow; but when working with bitwise operations, int will get you the JavaScript-like results, since then both platforms are operating on 32-bit numbers.
You should use long instead.
System.out.println(46022L*65535L); // = 3016051770
Java has ints and longs.
System.out.println(Integer.MAX_VALUE); // = 2147483647
System.out.println(Long.MAX_VALUE); // = 9,223,372,036,854,775,807
As for the language difference, I can only attribute it to different precisions between the languages. If you see this question, you'll see the largest number in JS is 9,007,199,254,740,992. That's a guess, it might be for another reason.

Operator in Java like // in python?

Is there a form of the // operator that is used in python that I can use in java, or some sort of workaround?
10 // 3 = 3
In python 3 // act as a floor division by default.
In python 2.2 and later 2.X version we can import it from the __future__
>>> from __future__ import division
>>> 10/3
3.3333333333333335
>>> 10//3
3
In Java:
When dividing floating-point variables or values, the fractional part of the answer is represented in the floating-point variable.
float f = 10.0f / 6.0f; // result is 1.6666
double d = 10.0 / 9.0; // result is 1.1111
But for floor in java:
(int)Math.floor(10/3);
One thing to notice is:
in python 3:
6 // -132 = -1
in java:
6 / -132 = 0
public static int python_like_divisor(int x, int y) {
final remainder = x % y;
if(remainder != 0) {
return (x - remainder) / y;
}
return x / y;
}
Some basic math knowledge is good ;)
With float-point (float, double etc.) values this method will not work properly.
Java's integer division will act in the same way as the // operator in Python. This means that something like this:
(int) 9/4 == 2 is True
The cast here is even unnecessary because both 9 and 4 are integers. If one was a float or a double this cast would be necessary as java would no longer execute this statement as integer division. To be more explicit you could do this
(int)Math.floor(9 / 4);
which divides the numbers first and then floors the results to the nearest integer.
You can use
java.lang.Math#floorDiv(int, int)

How to calculate ((Integer)^(double)) % (Integer) in java?

I am trying to calculate the value of (10^5.102103)%24 that is 10 raised to power 5.102103 modulus 24 in Java ?
Which is the best and accurate method to do because
int a;
double b;
int m;
Calculate (a^b)%m
Where a can be very large like upto 10^9
b can be any double or float value which can be large
and m is any Integer
Example ---How you can calculate the value of
(10^10002.3443)%10000007
I know Math.pow(a,b) function works for small a and b only
While BigInteger function Uses only modPow(a,b) where a and b should be integer only(Correct me if i am wrong)
Unfortunately, it's not possible using the normal Java data types to get a correct answer to this. If you use double to store the exponent, you introduce an error, because double won't store most decimal numbers exactly. When you write double b = 10002.3443; the number that is stored in b is actually 10002.34430000000065774656832218170166015625. Even though it looks like 10002.3443 when you print it, that's a trick of the way Java prints numbers - basically it chooses the decimal number with the least number of decimal places that would be represented by that double.
Now this difference looks insignificant. But the difference between 10^10002.3443 and 10^10002.34430000000065774656832218170166015625 is approximately 3.346 x 10^9990, which is a 9991-digit number. Now, what will this difference become when we apply the modulus operator?
(10^10002.34430000000065774656832218170166015625 % 10000007) - (10^10002.3443 % 10000007)
= (10^10002.34430000000065774656832218170166015625 - 10^10002.3443) % 10000007
= (3.346 x 10^9990) % 10000007 (approximately)
Now, it's anybody's guess what that actually comes to. But you've got a better chance of being struck by lightning than of getting the correct answer, if you use double at any point in the calculation.
The other option might be BigDecimal. But the problem is that 10^10002.3443 is irrational - it's not a terminating decimal, so it can't be represented correctly in a BigDecimal.
So Java doesn't have a data type that will allow you to perform the calculation that you want to perform.
You are going to have to invent your own data type, then work out how to do all the bit-crunching to implement exponentiation and modulus. This is a huge project, and I suggest you start out by getting yourself a PhD in mathematics.
(Note: Obviously, I am using ^ to indicate exponentiation and x to indicate multiplication in the above, even though this is not the normal Java convention)
Let's think back to discrete math!
Given y = a b (mod m), we know that
y = ((a mod m)^b) mod m
For example, if we have
a = 2, b = 6, m = 5
a raised to the power of b is 64. 64 mod m is 64 % 5 == 4. Let's check our algorithm:
4 == ((a mod m)^b) mod m
4 == ((2 mod 5)^6) mod 5
...
4 == 64 % 5
4 == 4
This doesn't really help us all too much (in its current form), so let's use modular arithmetic at every step to save the day.
int a = 10;
int m = 10000007;
double b = 10002.3443;
int holder = (int) b;
double delta = b - holder; // as close as we're going to get
int total = 1;
for (int i = 0; i < holder; i++) {
total *= (a % m); // multiply by the modulus
total %= m; // take the modulus again
}
total *= (Math.round(Math.pow(a, delta)) % m);
total %= m;

Compute the remainder of multiplying two long number?

I am writing a code for a crypto method to compute x^d modulo n using Repeated Squaring
public static long repeatedSquaring(long x, long d, long n){
x = x%n;
boolean dj = d % 2 == 1;
long c = dj ? x : 1;
d = d / 2;
while (d > 0){
dj = d % 2 == 1;
x = x * x % n; //Here
if (dj)
c = c * x % n; //and here..
d = d / 2;
}
return c;
}
This code work fine when n is small. But with n > sqrt(Long.MAX_VALUE)it gives an unexpected result.
Because with x ≈ n, we can have x*x > Long.MAX_VALUE and then the modulo operator give an incorrect value assign to x (or c).
So, my question is, how we can compute (A * B) % N (all are long type) using only math related method.
I don't want to use BigInteger (BigA.multiply(BigB).remainder(BigN) or we can use BigX.modPow(BigD, BigN) directly for the big problem).
I think that a normal computing will run faster than String computing? Morever with my problem, all temp values are long type 'enough'.
And I wonder that the solution will work fine with the worst case: A, B, N <≈ Long.MAX_VALUE.
multiplying can be done in log(B) time simliar to exponentiation
if(b is odd) a+multiply(2*a,(b-1)/2) mod N
else multiply(2*a,b/2) mod N
this works till longvalue/2
http://en.wikipedia.org/wiki/Montgomery_reduction might be more optimum
Really, the short answer is that you need to use BigInteger, even if you don't want to. As you've discovered, the approach you're currently taking will overflow the bounds of a long; even if you improve the algorithm, you still can't get more than 64 bits into the answer with a long.
You say you're using this for crypto; but 64-bit public key crypto is so weak that it is worse than not having it (because it gives a false sense of security). Even 1024 bits is not enough these days for public key, and 64 bits could be cracked more or less instantaneously.
Note that this is not the same as symmetric crypto, where the keys can be much smaller. (But even there, 64 bits is not enough to stop even an amateur hacker.)
See this question, where it was pointed out that 64-bit RSA can be cracked in a fraction of a second... and that was four years ago!

Categories

Resources