|
Pers.narod.ru. Тексты. Немного о машинном нуле или Паскаль точнее всех? |
Запустим простенькую программку для определения точности представления вещественных чисел (или машинного ноля) в нескольких разных средах...
Это результат из MathCAD 2001i:

А вот скриншот из MATLAB 7:

Аналогичная программа на Паскале (Turbo Pascal 7.1):
{$N+}
var eps:extended;
begin
eps:=1;
while 1+eps<>1 do eps:=eps/2;
writeln (eps);
reset (input); readln;
end.
выдала вот что:
5.42101086242752E-0020
т.е. 10-20! Для любого вещественного типа от real до extended. Надо заметить, что без включенной опции {$N+} (математический сопроцессор) Паскаль даст точность 4.5474735089E-13
По доке к Паскалю в нём есть 10-байтовые вещественные числа, в пакетах же под Windows используются обычно 8-байтовые.
Тип Диапазон Точность Байт Real 2.9e-39..1.7e38 11-12 6 Single 1.5e-45..3.4e38 7-8 4 Double 5.0e-324..1.7e308 15-16 8 Extended 3.4e-4932..1.1e4932 19-20 10 Comp -9.2e18..9.2e18 19-20 8
Вот для сравнения программа на Visual Basic for Applications, выполненная в Excel 2003:
Sub Кнопка1_Щелкнуть()
Dim eps As Double
Dim i As Long
i = 0
eps = 1
While 1 + eps <> 1
eps = eps / 2
i = i + 1
Wend
Worksheets("Лист1").Cells(1, 2).Value = eps
Worksheets("Лист1").Cells(1, 3).Value = i
End Sub
(здесь дополнительно считается число шагов, выполненных циклом). А вот скриншот с результатами её запуска:

Как видим, результат полностью совпадает с MATLAB, и неудивительно - те же 8-байтовые числа.
Документ HTML, делающий то же самое с помощью Javascript:
<html>
<head>
<title>Проверка машинного нуля</title>
</head>
<body>
<script type="text/javascript">
var eps=1;
var count=0;
while (1+eps!=1) { eps/=2; count++; }
document.writeln ('<p>Eps='+eps);
document.writeln ('<p>N='+count);
</script>
</body>
</html>
Результат на 100% совпадает с MATLAB и Excel:

Консольный Borland C++ 3.1 тоже неплох, ниже прилагается листинг аналогичной программы с закомментаренным выводом 2 последних шагов.
//63 2.16840434497100887000E-19
//64 1.08420217248550443000E-19
#include <stdio.h>
void main () {
long double eps=1;
long int n=0;
while (1+eps!=1) {
printf ("\n%ld %25.20LE",++n,eps);
eps/=2;
}
fflush (stdin);
getchar();
}
|
|