64 bit binary number representation in matlab without rounding off

조회 수: 37 (최근 30일)
Nits
Nits 2019년 7월 20일
댓글: Bruno Luong 2019년 7월 24일
I have a 64 bits binary number having 1's and 0's and i need this number in all 64 bits for further processing. However, i am getting this number in exponential form after rounding i.e. 1.01010101010101e+41. Can anyone please tell me how to get full 64 bits without losing precision ? Thanks in advance.

채택된 답변

Guillaume
Guillaume 2019년 7월 20일
If matlab shows the number is 1.01010101010101e+41 then you do not have a binary number. You have a decimal integer number consisting of just the digits 0 and 1. Additionally, that decimal number is stored as a 64-bit double.
Any integer number greater than flintmax (= 9007199254740992), so anything with 16 digits or more may not be stored exactly as a double. The greater the number, the less likely you can store it exactly. e.g 100000000000000010 (17 digits) is stored as 100000000000000016. There's nothing that can be done about that, that's the way double numbers work.
You could store your decimal representation as a 64-bit integer instead (uint64) to be able to store a few more digits but that won't get you far. The maximum decimal number consisting of 0s and 1s that you can store as uint64 is 11111111111111111111 (20 digits). Anything above that cannot be stored.
So, the first thing you need to realise is that you cannot store a number consisting of 64 0s and 1s as a decimal number, double or uint64 (unless you defer to the symbolic toolbox but that would be slow).
You could store it as a char vector, as suggested by Bruno.
In my opinion, the simplest way to store a 64-bit number is to store it in its decimal representation as a uint64 (i.e. store the binary 1111111111111111111111111111111111111111111111111111111111111111b as uint64(18446744073709551615)
  댓글 수: 21
Guillaume
Guillaume 2019년 7월 24일
Wow! It certainly wasn't obvious that the input was simply the digits of a uint64 integer.
Another way of obtaining the result:
B=[1;3;8;6;0;6;9;3;9;5;1;7;3;6;0;4;0;1;2;9];
C = sum(10.^uint64(numel(B)-1:-1:0) .* uint64(B'), 'native');
N = typecast(C, 'double')
Bruno Luong
Bruno Luong 2019년 7월 24일
"Wow! It certainly wasn't obvious that the input was simply the digits of a uint64 integer."
Actually I did suspect that since 10^20 covers just the maximum of uint64 numbers.
But to me the real surprise is casting uint64 in double!!! What's purpose (quick and dirtly crypting)? And what's the rounding issue he mentioned in the first post?

댓글을 달려면 로그인하십시오.

추가 답변 (3개)

KALYAN ACHARJYA
KALYAN ACHARJYA 2019년 7월 20일
편집: KALYAN ACHARJYA 2019년 7월 20일
num=1.01010101010101e+41;
format long g; % Put the format, its just change the display pattern
bin_num=dec2bin(num);
Result:
bin_num =
'10010100011010111100011011101001001110100101101001011000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
Please do the change as per your requirements
  댓글 수: 2
Guillaume
Guillaume 2019년 7월 20일
편집: Guillaume 2019년 7월 20일
Note that as per its documentation, dec2bin cannot convert accurately any number greater than flintmax (because it uses double representation internally), so it's not suitable for 64-bit integer. It fails miserably for e.g.
>> dec2bin(intmax('uint64'))
ans =
'10000000000000000000000000000000000000000000000000000000000000000'
when the answer should be
ans =
'1111111111111111111111111111111111111111111111111111111111111111'

댓글을 달려면 로그인하십시오.


Bruno Luong
Bruno Luong 2019년 7월 20일
편집: Bruno Luong 2019년 7월 20일
Assuming you have your binary in string of length 64 such as
b=repmat('0',1,64);
b([1 end])='1',
You can convert to uint64 integer class by
num = typecast(flip(uint32(bin2dec(reshape(b,32,2)'))),'uint64')
If you binary string has less than 64 chars you might need first to pad it with '0' in the head before casting
b = [repmat('0',1,64-length(b)) b]
  댓글 수: 2
Bruno Luong
Bruno Luong 2019년 7월 20일
편집: Bruno Luong 2019년 7월 20일
for num of class 'uint64' conversion to binary can be done like this
b = reshape(flip(dec2bin(typecast(num,'uint32'),32)),1,[])
This avoid the issue of inaccuracy when dec2bin applies directly on num > flintmax.
Nits
Nits 2019년 7월 20일
Thanks for your answer. However, the problem with this strategy is explained with the help of an example. Suppose i have a decimal number, num=-108.308 which I convert to binary using b = reshape(flip(dec2bin(typecast(num,'uint32'),32)),1,[]) and then converted to uint64 using num = typecast(flip(uint32(bin2dec(reshape(b,32,2)'))),'uint64'). Now, how am i going to decode this uint64 number to the original number, num=-108.308?

댓글을 달려면 로그인하십시오.


John D'Errico
John D'Errico 2019년 7월 21일
편집: John D'Errico 2019년 7월 21일
Maybe you are looking for something like this. I wrote a little utility recently that fully extracts the binary form of any numeric class.
num = 108.308
num =
108.308
>> B = num2bin(num)
B =
struct with fields:
Class: 'double'
Sign: 1
Exponent: 6
Mantissa: '11011000100111011011001000101101000011100101011000001'
BinaryExpansion: [6 5 3 2 -2 -5 -6 -7 -9 -10 -12 -13 -16 -20 -22 -23 -25 -30 -31 -32 -35 -37 -39 -40 -46]
BiSci: '1.1011000100111011011001000101101000011100101011000001 B6'
BiCimal: '1101100.0100111011011001000101101000011100101011000001'
>> sum(2.^B.BinaryExpansion)
ans =
108.308
>> B.Sign*sum(2.^B.BinaryExpansion) == num
ans =
logical
1
So B contains the bits that are in num, and shows the binary form of num in several ways, thus in a scientific binary form, and a binary form with a decimal point, and as a list of powers of 2, that can then be summed to recover num.
It thus allows you to easily recover the original number in num, and do so in a way that should be exact. It even understands what denormal numbers are.
I'll probably play with the names of the fields before I post it on the file exchange, but I've attached it to this answer.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by