Only 17% of all 64-bit Integers are products of two 32-bit integers
lemire.me
lemire.me
While I find the 17% number interesting to think about, "most" is far less interesting. Multiplication doesn't care about order so you're instantly cutting 2^64 possibilities down to about 2^63. That's a hair's breadth away from "most" already, and considering even a tiny amount of overlapping results gets you there.
What gets interesting is actually trying to quantify the overlapping results.
(Just by way of example, for n=2^33, 2n=2^34 but also =2^17*2^17)
E.g. 2^40 = 2^20 * 2^20[1] The bounds are important because they guarantee that there is at most one prime factor from that range and this ensures that we are not double counting anything. If the upper bound was larger than the square of the lower bound, then we would have to worry about double counting numbers with more than one large prime factor.
Like an odd number x times an even number y, x* y produces the same product as x* 2 and y/2
Same for a multiple of 3 c and and a non multiple of 3 d, c * d = c/3 * d*3
It's much worse than that. It's difficult for a 64-bit product to have the high bit set if the multiplicands are both no larger than 32 bits.
If I did the correct integral (the area inside the unit square above y=.5/x), then 15.34% of products should have the high bit set. That's much less than half but it's still happening constantly.
Not sure I understand.
Adding two 32 bit integers takes you to 33 bit integers. (1111 + 1111 = 11110).
Addition doesn't care about order, so you're instantly cutting 2^33 possibilities down to 2^32. Or so is your argument. But in reality you can reach nearly all of those 2^33 numbers.
The 2^64 number is the number of inputs. For an operation which is commutative, you expect the outputs to be 2^63+2^32 or smaller, since you’ve introduced symmetry.
Commutativity introduces a relation on pairs of 32 bit ints (a,b) ~ (b,a), which accounts for one bit of information. Thus, at most 50% of 64bit ints show up as products of 32 bit ints.
E.g., 6^2 = (223)3 = 2(233).
One of ~22 (ln(2^32)) perfect squares will be a square of perfect prime. Most won't.
(You can escape * with \: \*)
Information quantities are more meaningfully expressed in number of bits.
Having ~a quadrillion redundant bitstrings all mapping to NaN sounds pretty bad, but logarithmic/information utilization-wise, this is actually not too bad.
See "8087 Numeric Data Processor" page S-74: https://ethw.org/w/images/2/2f/Intel_8086_family_users_numer...
Unfortunately IEEE didn't bother specifying NaN propagation semantics so it ended up pretty useless.
Whether a 64-bit number can be written as the product of two 32-bit ones depends only on the prime factors of the 64-bit number - it's a property of the number itself, and apparently 17% of 64-bit numbers have this property.
However, since a * b = b * a, our input space has a lot of duplicate outputs. So from this alone you can conclude roughly half of the output space must be uncovered by any input pair, simply because there aren't enough input pairs.
Here's the multiplication table up to 9 (so for n=10 in place of n=2^64), and it already contains only 37 distinct products among its 100 entries:
× | 0 1 2 3 4 5 6 7 8 9
---+------------------------------
0 | 0 0 0 0 0 0 0 0 0 0
1 | 0 1 2 3 4 5 6 7 8 9
2 | 0 2 4 6 8 10 12 14 16 18
3 | 0 3 6 9 12 15 18 21 24 27
4 | 0 4 8 12 16 20 24 28 32 36
5 | 0 5 10 15 20 25 30 35 40 45
6 | 0 6 12 18 24 30 36 42 48 54
7 | 0 7 14 21 28 35 42 49 56 63
8 | 0 8 16 24 32 40 48 56 64 72
9 | 0 9 18 27 36 45 54 63 72 81
That is, in decimal, only 37% of (up to) two-digit numbers can be written as products of two one-digit numbers. This fraction, which drops to 28% at n=100, only drops to 17% at n=2^64 (per the article). So it decreases VERY slowly, and it's nontrivial that it actually goes to 0.And it's weakened even more by realizing that while you can get the raw fraction as low as you want, shrinking your list of products by n digits requires numbers with an exponential number of digits.
So whether “only 17%” is interesting or not depends on whether you see it as a stand-in for “less than half”, or “a number close to 0”.
(Posting this comment mainly to correct an error in my previous comment: in both places that I wrote “n=2^64” I should have instead written “n=2^32”.)
I think people would agree with that, yes. But that's a significantly weaker claim than your original one. The original version was "tends to 1 at large n" = "almost all", but this version is that once you reach large n it's "almost all". These different tests give completely different answers for the numbers you'd ever actually use.
And entirely separate from that, if you laid it out as "for 8 million* digit numbers, only one in a billion are products of 4 million digit numbers, so only enough to fill out 7,999,991 digits", I don't know if that really qualifies for "almost all" anymore. The fraction of hits is important, but so is the fraction of digits and entropy, and as you make the numbers bigger you approach 0.0% loss of digits and entropy.
* Placeholder number, I did not do the actual calculation here.
The chance of a random 64 bit integer being a 32 bit integer is 0.0000000233 %
The chance of a random 64 bit integer being a product of two 32 bit integers is 17%
Nice
Therefore the fact that relatively few 64-bit numbers are products of 32-bit integers means that a lot of pairs of 32-bit integers give by multiplication the same product.
X = ab and aY < 2^32 and bY < 2^32:
X × Y = X/a × aY = X/b × bY = Y × X = aY × X/a = bY × X/b
Which is 6 pairs resulting in the same product. This will be reduced if e.g. aY = X, but still...
This is more than just the prime numbers. For example, a 41-bit prime can be multiplied by 16 and it will still fit into 64 bits.
If you say that you want to be doing modular arithmetic instead of arithmetic, it doesn't look like 2 and 3 are enough. You're looking for a solution to
2ᵃ * 3ᵇ ≡ n (mod 2⁶⁴)
If n is even, we can supply any number of 2 factors by fiddling with a. We can assume without loss of generality that n is odd and a = 0. Now we want 3ᵇ ≡ n (mod 2⁶⁴)
for odd n.If I'm reading wikipedia correctly, we know that this will fail for some n:
https://en.wikipedia.org/wiki/Primitive_root_modulo_n
> In symbols, g is a primitive root modulo n if for every integer a coprime to n, there is some integer k for which gᵏ ≡ a (mod n).
This is what we want, with g = 3, k = b, a = n₁, and n₂ = 2⁶⁴. Our restriction that n₁ (our n) is odd satisfies the requirement that a be coprime to n₂ (wikipedia's n, the modulus).
The article continues:
> a primitive root exists modulo n if and only if n is 4, pᵏ or 2pᵏ for some odd prime number p and some k ≥ 0.
2⁶⁴ does not satisfy this requirement and therefore there is no primitive root modulo 2⁶⁴. As such, 3 is not a primitive root modulo 2⁶⁴.
I did say things would get complicated.
That should be "relatively few 20000000-bit integers", right?
My current comment itself, for instance, also doesn't really add anything to the discussion about the article and I'd have no expectation people leave it from going negative. Maybe the will, maybe they won't, but there is no reason to expect they should in principle of me loving tangents :D.
Most 1s won't go towards 1.5, but sometimes you're lucky.
Challenge accepted. Suppose we want to know the answer to 3 decimal places (so we'd match the headline). And suppose I allow my algorithm to be wrong one in a thousand times ("probably approximately correct").
Then sample some constant number C of random 64 bit integers. Run the following algorithm which separates each random sample into one of three classes: Y (has 32 but factors), N (does not have 32 bit factors), U (unknown).
Check if prime using probabilistic miller rabin. (Error prob goes to zero exponentially fast). If prime, return N. If it's not a prime, then run T steps of pollard rho to determine whether the number has 32 but factors; return Y,N, or U depending of the factors found up to step T.
The key observation is that T can be chosen to make the UNKNOWN class very small (with high probability), and so our estimate should rapidly converge to 17%Y, 83%N, ~0.001%U
For fixed error tolerance, this would run in roughly a constant number of iterations, independent of N.
Working on coding it up... it converges to 17±0.5%for N=64 bits in a javascript implementation relatively quickly, but for N=96, it really slows down as Pollard's Rho starts with large factors. This means my fast-and-loose assumption that "a constant number of iterations of Pollard Rho would work" isn't actually true!
Basically, replace the Pollard Rho partial factorization with a method of Kalai [1] for generating random numbers _together with their prime factors_.
I'm able to run this at about 30 samples per second at 160bits, giving an estimate of ~14.1% of 160-bit numbers factoring into two 80-bit numbers.
[1]: https://link.springer.com/article/10.1007/s00145-003-0051-5
By Erdos-Kac, almost all integers of size about n^2 have about log(log(n^2)) ~ log(log(n)) prime factors. However, almost all integers in the multiplication table have about 2*log(log(n)) prime factors.
Kevin Ford gets much more precise asymptotic estimates.
| n | factorization | products of two numbers
|-----|----------------|------------------------------------
| 50 | 2 * 5^2 | 1x50, 2x25, 5x10
| 60 | 2^2 * 3 * 5 | 1x60, 2x30, 3x20, 4x15, 5x12, 6x10
| 70 | 2 * 5 * 7 | 1x70, 2x35, 5x14, 7x10
| 75 | 3 * 5^2 | 1x75, 3x25, 5x15
| 80 | 2^4 * 5 | 1x80, 2x40, 4x20, 5x16, 8x10
| 84 | 2^2 * 3 * 7 | 1x84, 2x42, 3x28, 4x21, 6x14, 7x12
| 90 | 2 * 3^2 * 5 | 1x90, 2x45, 3x30, 5x18, 6x15, 9x10
| 96 | 2^5 * 3 | 1x96, 2x48, 3x32, 4x24, 6x16, 8x12
| 98 | 2 * 7^2 | 1x98, 2x49, 7x14Anyway here is a fun pattern you get when you multiply 8 bit unsigned integers. Not all pairs of (upper bits, lower bits) are reachable, and it has a lot of distinct patterns.
https://i.imgur.com/Gb3HDR0.png
(Should I host the image on GitHub Gists so it doesn't vanish?)
You have to redo the math to make the constraint work.
> There are 3,215,709,724,700,470,902 64-bit (unsigned) integers that can be written as a product of two 32-bit integers.
That can be written as a product of one or more pairs of 32 bit integers. So this is just not a bijective map.
Extremely strange way to deliver the headline (right before delivering the headline).