Why does the modulo function seem to break for large numbers?

18 ビュー (過去 30 日間)
Kiran KC 2021 年 11 月 5 日
コメント済み: Rik 2021 年 11 月 5 日
For part of a function I am writing that tests whether an input number is an integer.
The answer should be zero, because for any integer n, (n*10)/10 = n , Therefore, mod(n*10,10) = 0
But in this case of very large numbers (like the one in the screenshot above), it does not work. I would appreciate any explanations as to why this is and/or how to solve this problem?

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

採用された回答

Stephen 2021 年 11 月 5 日

You used a binary floating point number whose precision is limited to around 15-16 significant decimal digits.
The output of MOD is "correct" (even if those end digits are effectively noise):
format bank
x = 290384798012501645096234 % check the value stored in memory:
x =
290384798012501642969088.00
y = x*10 % and also the value stored after that multiplication:
y =
2903847980125016228364288.00
mod(y,10)
ans =
8.00
You could use the symbolic toolbox, which supports arbitrary integer lengths:
x = sym('290384798012501645096234')
x =
290384798012501645096234
y = x*10
y =
2903847980125016450962340
mod(y,10)
ans =
0
1 件のコメント表示非表示 なし
Kiran KC 2021 年 11 月 5 日
Makes sense, thank you for the detailed answer!

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

その他の回答 (1 件)

Steven Lord 2021 年 11 月 5 日
For sufficiently large numbers, not all numbers in that vicinity are representable in IEEE double precision. What's the distance between your number and the next largest number?
x = 290384798012501645096234;
eps(x)
ans = 33554432
So if I were to add a million to x, I still haven't gotten to the next largest number.
y = x + 1e6;
y == x % true
ans = logical
1
The same were to hold if I added a number that you would expect changes the last digit of x. In fact it's negligible enough relative to x that it doesn't change x at all.
y = x + 1234567;
y == x
ans = logical
1
If you want to work with numbers that large and represent each number in that vicinity, you're going to need to work symbolically.
s = sym('290384798012501645096234');
t = s + 1e6;
isAlways(s == t) % false
ans = logical
0
t = s + 1234567;
isAlways(s == t) % false
ans = logical
0
mod(s, 10)
ans =
4
3 件のコメント表示非表示 2 件の古いコメント
Rik 2021 年 11 月 5 日
That is not intended to be possible (it can happen in some rare cases where servers are slow to update, creating a sort of race condition, I don't know if this is still possible).
You can click the vote button and write a comment with a thank you.

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

R2019a

Community Treasure Hunt

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

Start Hunting!

Translated by