Can you trust in Matlab exact arithmetics ?

조회 수: 3 (최근 30일)
Dario
Dario 2020년 9월 5일
편집: John D'Errico 2020년 9월 5일
Try this example :
>> n=8
n =
8
>> sym(1/beta(n,n))
ans =
51480
>> sym(nchoosek(2*n-2,n-1)*(2*n-1))
ans =
51480
which is correct, the two expressions coincide and take an integer value for all positive integer n.
However already with n=9 something goes wrong:
>> n=9
n =
9
>> sym(nchoosek(2*n-2,n-1)*(2*n-1))
ans =
218790
>> sym(1/beta(9,9))
ans =
7517567157534725/34359738368
which is not an integer...

답변 (2개)

Ameer Hamza
Ameer Hamza 2020년 9월 5일
Specify one of the input to beta() as sym to indicate to MATLAB that you want to do symbolic mathematics with beta() function
>> sym(1/beta(sym(9),9))
ans =
218790

John D'Errico
John D'Errico 2020년 9월 5일
편집: John D'Errico 2020년 9월 5일
Trust is a difficult thing. Blind trust is a bad idea, as if you do anything you want, you may be mis-using the tools. And if you misuse any tool, bad things can happen.
Therefore, trust requires that you understand what you are doing. Trust is a two-way street. Thus, when you do this:
n=9;
sym(nchoosek(2*n-2,n-1)*(2*n-1))
ans =
218790
What happens in MATLAB? You need to understand what you are doing, BEFORE you place blind trust in anything. When you do this:
nchoosek(2*n-2,n-1)*(2*n-1)
MATLAB is operating on INTEGERS. Integers are stored EXACTLY as long as the integer does not exceed 2^53-1. That clearly did not happen here, so you can trust that result. SYM is able to now convert it to a sym. But the call to nchoosek there creates a DOUBLE PRECISION NUMBER. Then it passes that result to sym. Luckily, the output from nchoosek will always be an integer as long as it does not overflow the limit for a double as an integer.
Instead, what happens here?
sym(1/beta(9,9))
ans =
7517567157534725/34359738368
IT IS A BAD IDEA TO TRUST THIS. Why? Because if you do that, it means you made a mistake, IF your assumption is the result will be an integer.
What is beta(9,9)?
beta(9,9)
ans =
4.5706e-06
So MATLAB computes that result as a FLOATING point number, a double. It is NOT exactly the inverse of the integer you may think it is. It is a double. MATLAB cannot store floating point numbers like this exactly. You cannot store the inverse of 218790 exactly in a binary storage format. This is true of most rational fractions.
1/beta(9,9)
ans =
2.1879e+05
What is the number that was computed there?
sprintf('%0.55f',1/beta(9,9))
ans =
'218790.0000000001455191522836685180664062500000000000000000000'
So not exactly 218790, but something very close. Probably one bit is flipped down at the level of the least significant bit.
What was actually stored? A little work lets me recover the result as effectively:
2^17 + 2^16 + 2^14 + 2^12 + 2^10 + 2^9 + 2^7 + 2^5 + 2^2 + 2^1 + 2^-33 + 2^-35
But the binay decomposition of 218790 is just:
2^17 + 2^16 + 2^14 + 2^12 + 2^10 + 2^9 + 2^7 + 2^5 + 2^2 + 2^1
ans =
218790
Now, when you try to make that number you actually computed a sym, MATLAB does exactly what you told it to do! It creates a symbolic value that is EXACTLY what you gave it.
vpa(sym(1/beta(9,9)),55)
ans =
218790.00000000014551915228366851806640625
When you perform an operation like beta(9,9), it returns a double precision number. While you may think it should be the inverse of an integer, MATLAB does not know that. MATLAB does what you tell it to do.
So no, you cannot blindly "trust" something that you did without understanding what you were doing.

카테고리

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

Community Treasure Hunt

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

Start Hunting!

Translated by