Convert 64 bit numbers from binary to decimal with uint64
I want to convert 64 bit numbers from binary to decimal. Since dec2bin
only supports up to 52 bits, I thought I could flip my own function and use uint64
to go beyond that limit:
function [dec] = my_bin2dec(bin) v = uint64(length(bin)-1:-1:0); base = uint64(2).^v; dec = uint64(sum(uint64(base.*(uint64(bin-'0'))))); end
However, it doesn't work as expected:
my_bin2dec('111000000000000000000000000000000000001010110101011101000001110') ans = 8070450532270651392 my_bin2dec('111000000000000000000000000000000000001010110101011101000001111') ans = 8070450532270651392
While this is the correct result:
(111000000000000000000000000000000000001010110101011101000001110)bin = (8070450532270651918)dec (111000000000000000000000000000000000001010110101011101000001111)bin = (8070450532270651919)dec
What am I missing? It looks like there is still an operation in progress using 52 bit double arithmetic, but I don't know which one.
I checked whether the operation for available uint64
, and it seems like the ones that I use ( power
, times
, sum
), is:
>> methods uint64
Methods for class uint64:
abs bitxor diff isinf mod plus sum
accumarray bsxfun display isnan mpower power times
all ceil eq issorted mrdivide prod transpose
and colon find ldivide mtimes rdivide tril
any conj fix le ne real triu
bitand ctranspose floor linsolve nnz rem uminus
bitcmp cummax full lt nonzeros reshape uplus
bitget cummin ge max not round xor
bitor cumprod gt min nzmax sign
bitset cumsum imag minus or sort
bitshift diag isfinite mldivide permute sortrowsc
source to share
You were right in saying that
It seems that there is still an operation in progress using 52-bit double arithmetic.
Problem in line
dec = uint64(sum(uint64(base.*(uint64(bin-'0')))));
The operation sum(uint64(base.*(uint64(bin-'0'))))
produces a result double
that contains about 15 significant digits. This is why your lowest numbers are wrong. Converting to uint64
later does not help, since the accuracy is already lost.
The solution is to sum in uint64
. This gives the result uint64
with full precision:
dec = sum(uint64(base.*(uint64(bin-'0'))), 'native');
source to share
Had a thought like @beaker split it into chunks:
%% dec2bin x=intmax('uint64') MSBs = dec2bin( bitshift(x,-32) ,32) LSBs = dec2bin( bitand(x, hex2dec('FFFFFFFF')) ,32) y = [MSBs LSBs] %% bin2dec MSBs = y(1:32) LSBs = y(33:64) z = bitor( bitshift( uint64(bin2dec(MSBs)) , 32 ) , uint64(bin2dec(LSBs)) ) % (now x = z)
Oddly enough, it dec2bin
doesn't seem to give an error, but gives incorrect answers for 64-bit numbers:
dec2bin( intmax('uint64') ) ans = 10000000000000000000000000000000000000000000000000000000000000000
source to share