unsigned long long
is a limited-length integer format (probably 64bit or more). That means that it can hold no value larger than 264-1.
A BigInteger
is an arbitrary-length integer format. That means that the size of the number stored in a BigInteger
is effectively limited only by the available memory (and some JVM restrictions like the size of an array, but those are pretty big).
Somewhere in your calculation in the C program the unsigned long long
probably overflows and you get a cut-off result.
That doesn't happen with BigInteger
(it never silently overflows), it will just give the exact result.
You can emulate an overflow by creating a BigInteger
that holds the desired bit mask (64 set bits) and using myValue.and(MASK)
to get the "overflown" result.
You'd have to do that at every step where an overflow could occur, 'though. And it would certainly be slower than the C code.