What is the max number of digits allowed for a base 2 number?

I am working with base 10 integers in the quadrillion range. My understanding is that when converted to base 2, such numbers end up being about 50 digits. What is the max number of digits MATLAB allows for base 2 numbers?

Answers (1)

The default data type in MATLAB is "double", which means 64 bits. When used to represent a base 2 number, its maximum value is 2^64-1 (the value of intmax('uint64')), which is significantly larger than a quadrillion (10^15).
For 64 bits or under, you can use bin2dec() directly.
quadrillion =10^15
quadrillion = 1.0000e+15
a=uint64(2^64-1)
a = uint64 18446744073709551615
double(a)
ans = 1.8447e+19
intmax('uint64')
ans = uint64 18446744073709551615
dec2bin(a)
ans = '1111111111111111111111111111111111111111111111111111111111111111'
dec2bin(quadrillion)
ans = '11100011010111111010100100110001101000000000000000'
dec2hex(a)
ans = 'FFFFFFFFFFFFFFFF'
dec2hex(quadrillion)
ans = '38D7EA4C68000'
bin2dec(repmat('1',[1,64]))
Warning: Binary numbers representing integers greater than or equal to flintmax might not be represented exactly as double-precision floating-point values.
ans = 1.8447e+19
bin2dec(repmat('1',[1,65]))
Error using bin2dec
Binary text has too many digits for specified or implied type suffix.

9 Comments

bin2dec() returns a double precision value. Double precision has 53 significant bits, so values greater than 2^53 might not be represented properly.
Converting values with 50 significant bits should be fine.
This answer is misleading. IEEE 64-bit double precision only has 52-bits in the significand, 53-bits if you include the hidden leading bit. It simply can't represent all the binary bits for anything larger. Your example is simply spitting out the max uint64 value. E.g.
format longg
2^64
ans =
1.84467440737096e+19
num2hex(2^64)
ans = '43f0000000000000'
num2hex(2^64-1)
ans = '43f0000000000000'
num2hex(2^64-1000)
ans = '43f0000000000000'
Why are these the same? Because the 1 and 1000 are both well below the eps(2^64) value:
eps(2^64)
ans =
4096
So you end up with the same result because the inputs are actually exactly the same:
sprintf('%20.0f',2^64)
ans = '18446744073709551616'
And this number actually overflows the max uint64 value, so what you get in the conversions below is simple range clipping at the upper value:
uint64(2^64)
ans = uint64
18446744073709551615
uint64(2^64-1)
ans = uint64
18446744073709551615
uint64(2^64-1000)
ans = uint64
18446744073709551615
You need to stay under flintmax if you want to work with binary number conversions with doubles and maintain all the significant bits.
flintmax
ans =
9.00719925474099e+15
log2(flintmax)
ans =
53
You are right. Using 2^64-1 or 2^64-2 is incorrect because it uses "double" size floating point data. However, the point holds true that MATLAB readily supports 64 bits of integer data.
dec2bin(intmax('uint64'))
ans = '1111111111111111111111111111111111111111111111111111111111111111'
dec2bin(intmax('uint64')-1)
ans = '1111111111111111111111111111111111111111111111111111111111111110'
dec2bin(intmax('uint64')-2)
ans = '1111111111111111111111111111111111111111111111111111111111111101'
If you want to use arithmetic to create the uint64 value 2^64-2 carefully you could do:
two = uint64(2);
x = two*(two^63-1) % Avoid computing 2^64 directly
x = uint64 18446744073709551614
y = intmax('uint64')-1 % (2^64-1)-1
y = uint64 18446744073709551614
This is the same type of approach I use when creating large symbolic values without going through double precision first.
T = sym(2);
q = T^2000-1 % greater than realmax
q = 
114813069527425452423283320117768198402231770208869520047764273682576626139237031385665948631650626991844596463898746277344711896086305533142593135616665318539129989145312280000688779148240044871428926990063486244781615463646388363947317026040466353970904996558162398808944629605623311649536164221970332681344168908984458505602379484807914058900934776500429002716706625830522008132236281291761267883317206598995396418127021779858404042159853183251540889433902091920554957783589672039160081957216630582755380425583726015528348786419432054508915275783882625175435528800822842770817965453762184851149029375
lastDigit = mod(q, 10) % last digit is in fact odd as expected
lastDigit = 
5
I = 2^2000-1 % Overflows to infinity in double precision
I = Inf
S = sym(2^2000-1) % Too late, already Inf before sym gets called
S = 
dec2bin() is able to handle uint64.
Unfortunately though, bin2dec() can only reliably handle up to flintmax.
This is incorrect:
"The default data type in MATLAB is "double", which means 64 bits. When used to represent a base 2 number, its maximum value is 2^64-1 "
Yes, a double does use 64 bits, or 8 bytes. And, a double is the default daya type. But that is where your correct-ness ends.
A DOUBLE in MATLAB does NOT store 64 bits in the way you state. It stores 52 bits of precision, combined with a sign bit, and the remaining 11 bits to store an exponent.
As such, the largest number a double can store exactly is flintmax = 2^53-1, thus the largest integer you can store with 52 binary bits. That is the largest base 2 number a double can store exactly. If you exceed that point, then a double fails to provide exact storage.
X = flintmax('double')
X = 9.0072e+15
num2str(X,55)
ans = '9007199254740992'
But now see that if we try to increment X by 1, a double has a problem.
X + 1 == X
ans = logical
1
Yes, a UINT64 number can store 64 bits as an unsigned integer. But UINT64 is a very different thing from a double, and it is NOT the default data type in MATLAB.
Yes. I should not have mentioned the "double" data type. I shall say that MATLAB has the int64 and uint64 data type for the OP's need.
intmax('uint64')
ans = uint64 18446744073709551615
a=intmax('uint64')-1
a = uint64 18446744073709551614
dec2bin(a)
ans = '1111111111111111111111111111111111111111111111111111111111111110'
class(uint64(10)-1)
ans = 'uint64'
Do note that as many of us have said, if you're working with numbers near intmax('uint64') you need to be a bit careful with how you create them. Simply defining them numerically and calling uint64 on the result won't necessarily work.
x = uint64(2^64-(1:4))
x = 1×4
18446744073709551615 18446744073709551615 18446744073709551615 18446744073709551615
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
By the time MATLAB "sees" the uint64 call it's already performed the calculation in double precision. How far apart are numbers on the order of 2^64 spaced?
eps(2^64)
ans = 4096
This differs from
x = uint64(2^64)-uint64(1:4)
x = 1×4
18446744073709551614 18446744073709551613 18446744073709551612 18446744073709551611
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
The 2^64 gets evaluated in double precision. Then uint64() gets applied and saturates the 2^64 to (2^64-1). Then the subtraction takes place.
Compare
x = uint64(18446744073709551615) - uint64(0:3)
x = 1×4
18446744073709551615 18446744073709551614 18446744073709551613 18446744073709551612
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
In this case, uint64(LITERALCONSTANT) is parsed as a uint64 value without loss of precision -- but that parsing only applies to literal constants, not to expressions (even if the expressions are effectively constant)

Sign in to comment.

Products

Release

R2023b

Asked:

on 4 Feb 2025

Commented:

on 5 Feb 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!