При работе над простым осуществлением программирования я произвел некоторое время цикл (цикл типа DO в Фортране), который был предназначен для выхода, когда реальная переменная достигла точного значения.
Я заметил, что из-за используемой точности, равенство никогда не встречалось, и цикл стал бесконечным. Это, конечно, не неслыханно, и каждому сообщают, что, вместо того, чтобы сравнить два числа для равенства, это является лучшим, видят, являются ли абсолютной разностью между двумя числами меньше, чем порог набора.
То, что я нашел неутешительным, было то, как низко я должен был установить этот порог, даже с переменными в двойной точности, чтобы мой цикл вышел правильно. Кроме того, когда я переписал "дистиллированную" версию этого цикла в Perl, у меня не было проблем с числовой точностью и циклом штраф, из которого выходят.
Так как код для создания проблемы является настолько маленьким, и в Perl и в Фортране, я хотел бы воспроизвести его здесь в случае, если я заминаю важную деталь:
Код Фортрана
PROGRAM precision_test
IMPLICIT NONE
! Data Dictionary
INTEGER :: count = 0 ! Number of times the loop has iterated
REAL(KIND=8) :: velocity
REAL(KIND=8), PARAMETER :: MACH_2_METERS_PER_SEC = 340.0
velocity = 0.5 * MACH_2_METERS_PER_SEC ! Initial Velocity
DO
WRITE (*, 300) velocity
300 FORMAT (F20.8)
IF (count == 50) EXIT
IF (velocity == 5.0 * MACH_2_METERS_PER_SEC) EXIT
! IF (abs(velocity - (5.0 * MACH_2_METERS_PER_SEC)) < 1E-4) EXIT
velocity = velocity + 0.1 * MACH_2_METERS_PER_SEC
count = count + 1
END DO
END PROGRAM precision_test
Код Perl
#! /usr/bin/perl -w
use strict;
my $mach_2_meters_per_sec = 340.0;
my $velocity = 0.5 * $mach_2_meters_per_sec;
while (1) {
printf "%20.8f\n", $velocity;
exit if ($velocity == 5.0 * $mach_2_meters_per_sec);
$velocity = $velocity + 0.1 * $mach_2_meters_per_sec;
}
Закомментированная строка в Фортране - то, что я должен был бы использовать, чтобы цикл обычно выходил. Заметьте, что порог устанавливается к 1E-4, который я чувствую, довольно вызывает жалость.
Названия переменных происходят от self-study-based, программирующего осуществление, которое я выполнял, и не имейте никакой уместности.
Намерение состоит в том, что цикл останавливается, когда скоростная переменная достигает 1700.
Вот усеченные выводы:
Вывод Perl
170.00000000
204.00000000
238.00000000
272.00000000
306.00000000
340.00000000
...
1564.00000000
1598.00000000
1632.00000000
1666.00000000
1700.00000000
Вывод Фортрана
170.00000000
204.00000051
238.00000101
272.00000152
306.00000203
340.00000253
...
1564.00002077
1598.00002128
1632.00002179
1666.00002229
1700.00002280
Каковы хороший скорость Фортрана и простота распараллеливания, если его точность воняет? Напоминает мне об этих трех способах сделать вещи:
Правильный путь
Неправильный путь
Питание Max путь
"Это не просто неправильный путь?"
"Да! Но быстрее!"
Все ребячество в стороне, я должен делать что-то не так.
Фортран имеет свойственные ограничения на числовую точность по сравнению с другими языками, или действительно ли я (довольно вероятен) тот в отказе?
Мой компилятор является gfortran (gcc версия 4.1.2), Perl v5.12.1, на Двухъядерном AMD Opteron 1 ГГц.