accuracy problems in uint64 numbers

I encrypt uint64 numbers. Number x which encrypted as, for example, 9824265115183455531 decrypted as 9824265115183455488. This difference affects the final decrypted text. Is Matlab not gives accurate results when operates on uint64? how I overcome this problem?

4 件のコメント

James Tursa
James Tursa 2019 年 9 月 18 日
Please show us your code. Perhaps you are doing intermediate calculations in double and that is causing your loss of trailing digits problem.
Walter Roberson
Walter Roberson 2019 年 9 月 18 日
I think it must be something else, perhaps loss of precision on an intermediate step involving smaller numbers.
>> double(uint64(9824265115183455531)) - uint64(9824265115183455488)
ans =
uint64
768
>> uint64(double(uint64(9824265115183455531)))
ans =
uint64
9824265115183456256
Ansam Osamah
Ansam Osamah 2019 年 9 月 18 日
I implemented my code on uint8 numbers to test the correctness of code. everything was OK and the decrypted text was correct. but when I implemented the same code on uint64, I gained a wrong result.
Walter Roberson
Walter Roberson 2019 年 9 月 18 日
Sorry, it is a cloudy night here and my telescope cannot see your computer screen.

サインインしてコメントする。

 採用された回答

Steven Lord
Steven Lord 2019 年 9 月 18 日

1 投票

It really depends on how you performed your computations. Let's take a somewhat large number, 3^40.
xDouble = 3^40;
xUint64 = uint64(3)^40;
areTheseTheSame = [uint64(xDouble); xUint64]
The answer to the implied question is no. The reason the two elements of areTheseTheSame are not the same is that 3^40 is greater than flintmax.
isGreaterThanFlintmax = xDouble > flintmax % true
The key statement in the flintmax documentation is "Above this value, double-precision format does not have integer precision, and not all integers can be represented exactly." The next largest representable number above flintmax is not flintmax+1 but flintmax+2.
>> F1 = flintmax;
>> F2 = flintmax + 1;
>> F1 == F2
ans =
logical
1
>> eps(flintmax)
ans =
2
>> F3 = flintmax + 2;
>> F1 == F3
ans =
logical
0
However, 3^40 is less than the maximum value that you can store in a uint64 so it can be exactly represented in uint64.
isLessThanMaximumUint64 = xUint64 < intmax('uint64') % true
If your computations are likely to result in large (greater than flintmax) integer values, you should probably operate on values stored in an integer data type as much as you can, like I did when I computed xUint64 by computing mpower (the ^ operator) on a uint64 value.

7 件のコメント

Ansam Osamah
Ansam Osamah 2019 年 9 月 19 日
Thank you for your concern, but I think the problem that faces me is different. I am about encrypting image using Threefish block cipher. I traced my code again and I think the problem is in converting the uint64 numbers from binary to decimal
suppose:
% plain_text='This is';
plain_binary=''0101010001101000011010010111001100100000011010010111001100100000';
plain_uint64=uint64(bin2dec(plain_binary(1:32))*2^32+ bin2dec(plain_binary(33:64)));
plain_uint64=6082227239949792256
but plain_binary is actally equal ‭6082227239949792032
these differences in the intermediate results make the final result completely different
Isn't that right?
James Tursa
James Tursa 2019 年 9 月 19 日
This is what everyone has been warning you about. All that stuff inside the uint64( ) conversion are intermediate calculations that are not done in uint64 arithmetic. So force it to use uint64 arithmetic in your example:
>> plain_uint64=uint64(bin2dec(plain_binary(1:32))*uint64(2)^32+ bin2dec(plain_binary(33:64)))
plain_uint64 =
6082227239949792032
Ansam Osamah
Ansam Osamah 2019 年 9 月 19 日
Thank you very much
Walter Roberson
Walter Roberson 2019 年 9 月 19 日
Unfortunately bin2dec returns a double, not a uint64.
Another approach is to bin2dec 8 bits at a time, uint8() that, and then typecast to uint64. You can do the same thing up to uint32 as the carrier type. But be careful because the bit order of dec2bin is big-endian (msb is to the left and bit significance strictly decreases to the right) but the bit order of all current matlab implementations is little-endian so swapping bytes might be needed depending what you do with the results.
Ansam Osamah
Ansam Osamah 2019 年 9 月 20 日
編集済み: Ansam Osamah 2019 年 9 月 20 日
Thank you very much
But, what about dec2bin for uint64
K>> dec2bin(uint64(8417341953491579463),64)
ans =
0111010011010000011001111110100011100010110110111011010000000000
but it is actually
‭0111010011010000011001111110100011100010110110111011001001000111
Walter Roberson
Walter Roberson 2019 年 9 月 20 日
dec2bin() converts its input to double before working out the binary.
u64 = uint64(8417341953491579463);
reshape(dec2bin(typecast(swapbytes(u64),'uint8'),8).',1,[])
Ansam Osamah
Ansam Osamah 2019 年 9 月 20 日
Thank you very much to all, your advice helped me too much

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Community Treasure Hunt

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

Start Hunting!

Translated by