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   

      

+2


source to share


2 answers


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');

      

+4


source


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

      

+1


source







All Articles