Trong khi làm việc trên một bài tập lập trình đơn giản, tôi tạo ra một vòng lặp while (vòng lặp DO trong Fortran) có nghĩa là để thoát ra khi một biến thực đã đạt đến một giá trị chính xác.Fortran có những giới hạn cố hữu về tính chính xác về số so với các ngôn ngữ khác không?
Tôi nhận thấy rằng do độ chính xác được sử dụng, sự bình đẳng chưa bao giờ được đáp ứng và vòng lặp trở thành vô hạn. Đây là, tất nhiên, không phải không nghe và một là thông báo rằng, thay vì so sánh hai con số cho bình đẳng, tốt nhất là xem nếu sự khác biệt tuyệt đối giữa hai con số nhỏ hơn một ngưỡng thiết lập.
Điều tôi thấy thất vọng là mức độ thấp đến mức tôi phải đặt ngưỡng này, ngay cả với các biến ở độ chính xác gấp đôi, cho vòng lặp của tôi để thoát đúng cách. Hơn nữa, khi tôi viết lại một phiên bản "chưng cất" của vòng lặp này trong Perl, tôi không gặp vấn đề gì về độ chính xác về số và vòng lặp thoát ra tốt.
Kể từ khi mã để tạo ra vấn đề là quá nhỏ, trong cả hai Perl và Fortran, tôi muốn tái tạo nó ở đây trong trường hợp tôi đang glossing qua một chi tiết quan trọng:
Fortran Mã
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 Mã dòng
#! /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;
}
Các nhận xét ra trong Ví tran là những gì tôi sẽ cần phải sử dụng cho các vòng lặp để thoát khỏi bình thường. Lưu ý rằng ngưỡng được đặt thành 1E-4, điều tôi cảm thấy khá thảm hại.
Tên của các biến đến từ bài tập lập trình tự học dựa trên tôi đã thực hiện và không có bất kỳ sự liên quan nào.
Mục đích là vòng lặp dừng lại khi biến vận tốc đạt đến 1700.
Sau đây là các kết quả đầu ra cắt ngắn:
Perl Output
170.00000000
204.00000000
238.00000000
272.00000000
306.00000000
340.00000000
...
1564.00000000
1598.00000000
1632.00000000
1666.00000000
1700.00000000
Fortran Output
170.00000000
204.00000051
238.00000101
272.00000152
306.00000203
340.00000253
...
1564.00002077
1598.00002128
1632.00002179
1666.00002229
1700.00002280
gì tốt là tốc độ và dễ song song nếu độ chính xác của nó stinks Fortran không? Nhắc tôi về ba cách để làm những việc:
The Right Way
The Way sai
Các Max Power Way
"Đó không phải là chỉ sai đường?"
" Vâng! Nhưng nhanh hơn!"
Tất cả đùa sang một bên, tôi phải làm gì đó sai.
Liệu Fortran có những hạn chế cố hữu về tính chính xác số so với các ngôn ngữ khác, hay tôi (rất có thể) người có lỗi?
trình biên dịch của tôi là gfortran (gcc phiên bản 4.1.2), Perl v5.12.1, trên một dual Core AMD Opteron @ 1 GHZ.
Không nên là số 3 "Cách điện tối đa"? – detly
Rất tiếc. Bạn đúng. Cảm ơn! – EMiller
Fortran đang sử dụng một đôi ở đây và tôi nghi ngờ Perl để làm như vậy. Nhưng việc kiểm tra một số điểm bằng với số dấu phẩy động là vấn đề (trừ khi bạn có số "an toàn" như '0,0144'). Vì vậy, tôi sẽ nói rằng nó có lẽ là phương pháp thử nghiệm của bạn đó là sai. – Wolph