Никогда не предполагайте, что число вроде vpa(sin(pi/4)) является точным с полной точностью, потому что MATLAB обычно вычисляет число внутри вызова vpa, используя арифметику с плавающей запятой, то есть с точностью до 16 цифр.
Однако, похоже, здесь это правильно. Например, мы знаем, что
sin(pi/4) == sqrt(2)/2
Давайте проверим этот результат. Я буду использовать 100-значную точность, сравнивая как vpa, так и мои собственные инструменты HPF.
>> vpa(sin(pi/4),100)
ans =
0.7071067811865475244008443621048490392848359376884740365883398689953662392310535194251937671638207864
>> vpa(sqrt(sym(2))/2,100)
ans =
0.7071067811865475244008443621048490392848359376884740365883398689953662392310535194251937671638207864
>> sqrt(hpf(2,100))/2
ans =
0.7071067811865475244008443621048490392848359376884740365883398689953662392310535194251937671638207864
>> sin(hpf('pi',100)/4)
ans =
0.7071067811865475244008443621048490392848359376884740365883398689953662392310535194251937671638207864
Итак, я предполагаю, что синтаксический анализатор распознал ввод как нечто, что символический набор инструментов может вычислить более точно. Но, как я уже говорил, будьте осторожны. Что такое грех(пи/12)?
>> vpa(sin(pi/12),100)
ans =
0.25881904510252073947640383266843855381011962890625
>> vpa('sin(pi/12)',100)
ans =
0.2588190451025207623488988376240483283490689013199305138140032073150569747488019969223679746942496655
>> vpa(sin(sym('pi')/12),100)
ans =
0.2588190451025207623488988376240483283490689013199305138140032073150569747488019969223679746942496655
>> sin(hpf('pi',100)/12)
ans =
0.2588190451025207623488988376240483283490689013199305138140032073150569747488019969223679746942496655
Видите, что в первом случае парсер нас не спас. В остальных случаях я заставлял MATLAB вычислять правильное значение. Фактически, небольшое усилие даст нам значение sin(pi/12) как sqrt(2)*(sqrt(3) - 1)/4.
>> DefaultNumberOfDigits 100
>> (sqrt(hpf(3)) - 1)*sqrt(hpf(2))/4
ans =
0.2588190451025207623488988376240483283490689013199305138140032073150569747488019969223679746942496655
Дело в том, что не доверяйте синтаксическому анализатору, чтобы спасти вас здесь.
Редактировать: в качестве проверки комментария Амро я с уважением заявляю, что MATLAB делает здесь что-то интересное. Посмотрите, что vpa может вернуть правильные первые 100 цифр числа пи, даже если число пи передано как число с двойной точностью. Поскольку число пи (как двойное) неверно после 16-й десятичной цифры, происходит что-то подозрительное.
>> vpa(pi,100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
>> vpa('pi',100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
vpa('pi',100) - vpa(pi,100)
ans =
0.0
В качестве проверки этого факта давайте посмотрим, что находит HPF. HPF фактически принимает значение IEEE 754, хранящееся в двойном значении, а затем преобразует его в число HPF.
>> hpf(pi,100)
ans =
3.141592653589793115997963468544185161590576171875
>> hpf('pi',100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
>> hpf('pi',100) - hpf(pi,100)
ans =
0.0000000000000001224646799147353177226065932275001058209749445923078164062862089986280348253421170679821480800000000
Итак, ясно, что MATLAB способен распознавать число пи как нечто большее, чем просто значение двойной точности, в котором оно будет передано.
Редактировать2:
На самом деле, немного игры говорит мне, что здесь происходит. VPA сложный, а не синтаксический анализатор. Рассмотрим дробь 7/13. Если мы построим его как двойное, а затем распечатаем значение с плавающей запятой, сохраненное во всей красе, мы увидим, что оно не совсем точное. Это ожидаемо.
>> sprintf('%.100f',7/13)
ans =
0.5384615384615384359179302009579259902238845825195312500000000000000000000000000000000000000000000000
7/13 — повторяющееся десятичное число. Вот правильные цифры:
>> vpa('7/13',100)
ans =
0.5384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615385
Теперь предположим, что мы пытаемся создать такое же число. Здесь я передам 7/13 как двойное, но ошибусь в младших десятичных цифрах
>> sprintf('%.100f',0.538461538461538461777777777)
ans =
0.5384615384615384359179302009579259902238845825195312500000000000000000000000000000000000000000000000
Здесь мы видим, что vpa ловит и исправляет «ошибку», которую я сделал, признавая, что то, что я передал, на самом деле точно такое же значение, как и при передаче в 7/13.
>> vpa(0.538461538461538461777777777,100)
ans =
0.5384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615384615385
Конечно, если я передам значение в виде строки, то vpa ошибется.
>> vpa('0.538461538461538461777777777',100)
ans =
0.538461538461538461777777777
Это объясняет, почему vpa может уловить и правильно вычислить vpa(sin(pi/4),100) с требуемой точностью. sin(pi/4) вычисляется как двойное число, но тогда vpa видит его как число, такое же, как версия sqrt(2)/2 с двойной точностью.
Будьте осторожны, конечно. Например, vpa недостаточно умен, чтобы поймать этот простой сдвиг числа пи.
>> vpa(pi + 1,100)
ans =
4.141592653589793115997963468544185161590576171875
>> vpa(pi,100)
ans =
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
person
Community
schedule
03.06.2012