2015-08-12 19 views
5

Có thể đặt biến tham số với NaN không? và có điều đó trong một mô-đun cụ thể. Tôi muốn sử dụng nó để khởi tạo một số biến khác. Vì vậy, tôi sẽ phải đối mặt với một lỗi thời gian chạy, nếu chúng không được cập nhật, thay vì mô phỏng chạy với một số số ngẫu nhiên. Tôi đang sử dụng GFORTRAN.Có biến tham số (hằng số) với giá trị NaN trong FORTRAN

+3

Đối với gfortran, tôi sẽ bị cám dỗ chỉ xem xét '-finit-real = nan'. – francescalus

Trả lời

5

Có thể. Trước tiên, bạn phải tìm ra mẫu bit nào đại diện cho một trong các giá trị NaN có thể có. Bạn có thể lưu trữ các mẫu bit trong một số nguyên:

use, intrinsic :: iso_fortran_env 
real(real64) x 
integer(int64) i 
x = 0 
x = 0/x 
print *, x 
print *, transfer(x, i) 
end 

Nó cung cấp cho: -2251799813685248

Sau đó, bạn có thể khởi tạo các biến của bạn sử dụng

real(real64), parameter :: nan64 = transfer(-2251799813685248_int64, 1._real64) 

Tương tự như vậy đối với 32 biến chút bạn sẽ có được số nguyên - 4194304, để bạn có thể làm

real(real32), parameter :: nan32 = transfer(-4194304_int32, 1._real32) 

Nhiều trình biên dịch có tùy chọn để làm điều đó cho bạn cho tất cả các biến thực. Như francescalus cho thấy, trong gfortran nó là -finit-real=nan. Làm điều đó bằng tay cho phép bạn kiểm soát tốt hơn.

Tuyên bố từ chối trách nhiệm: Cẩn thận khi chuyển sang nền tảng khác. Endianness và các vấn đề khác có thể đóng một vai trò, mặc dù tôi nghĩ rằng nó có thể được thực sự OK. Tôi giả định một CPU tuân thủ IEEE.


Xem, câu trả lời của câu trả lời cho một giải pháp thay thế sử dụng chức năng chuẩn. Thật không may, nó không áp dụng cho các hằng số parameter, nhưng rất hữu ích.

+0

Tôi đồng ý với đề xuất của bạn @Vladimir F theo cách này trong thời gian chạy, có thể thay đổi giá trị của biến thành NaN hoặc ngược lại. Nhưng nhược điểm là mẫu bit phụ thuộc vào máy của NaN. – Sorush

6

Để thêm vào Vladimir F's answer Tôi sẽ đề cập đến rằng gfortran 5.0 (nhưng không sớm hơn) hỗ trợ các mô-đun nội tại IEEE.

Thay vì

real x 
x=0 
x=0/x 

người ta có thể sử dụng

use, intrinsic :: iso_fortran_env 
use, intrinsic :: ieee_arithmetic 
integer(int32) i 
real(real32) x 

x = ieee_value(x, ieee_quiet_nan) 
i = transfer(x,i) 

này cung cấp cho bạn một sự linh hoạt ít hơn mà của NaN giá trị bạn nhận được. Bạn cũng không cần phải lo lắng về bất kỳ cờ báo hiệu không hợp lệ nào. [Nhưng lưu ý rằng yêu cầu ieee_signaling_nan có thể không thực sự cung cấp cho bạn điều đó.]

Lưu ý rằng không thể sử dụng trực tiếp ieee_value() khi tham chiếu: tham chiếu đến nó không phải là cụm từ không đổi. Để sử dụng như vậy, hãy sử dụng phương pháp này để lấy mẫu bit và áp dụng phương thức của câu trả lời khác.

Bạn cũng sẽ cần đảm bảo rằng có hỗ trợ cho các tính năng cho từng loại dữ liệu.

+0

Đúng, tôi vẫn không đi quá nhiều vào điều này, vì tôi phải giữ khả năng tương thích với gfortran 4.8. Thật không may, 'ieee_value' thực sự không được cho phép trong các biểu thức liên tục, vì vậy vẫn cần sử dụng phương thức transfer(). Thảo luận nhiều hơn là trong https://groups.google.com/forum/#!msg/comp.lang.fortran/tYC3UgAyNrY/6TzOLbkP6tsJ –

+0

Có vẻ như nếu tôi muốn sử dụng NaN để gỡ lỗi và nhận được lỗi thời gian chạy, tôi có để sử dụng tín hiệu NaN chứ không phải là tín hiệu yên tĩnh ([Ref] (http://stackoverflow.com/questions/18118408/what-is-difference-between-quiet-nan-and-signaling-nan)). – Sorush

+0

@Sorush Có. Không có gì đảm bảo rằng 'ieee_signaling_nan' sẽ dẫn đến một điều như vậy (mặc dù nó được khuyến nghị). Tôi không biết những gì gfortran trả về - nếu bạn có thể kiểm tra, hãy cho tôi biết. Một NaN yên tĩnh vẫn có giá trị, theo một nghĩa nào đó: bạn biết có gì đó không ổn. Không thuận tiện cho việc gỡ lỗi. – francescalus

0

Nếu bạn đang mắc kẹt với GFortran không có bản chất IEEE nhưng có iso_c_binding nội tại (như cái cần thiết để xây dựng R trên Windows), các công trình sau và tương đương với C và R NaN is.nan vào R):

real(kind = c_double), parameter :: ONE = 1_c_double  
real(kind = c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', ONE) 

Điều thú vị là real(kind = c_double), parameter :: NAN = TRANSFER(z'7FF0000000000001', 1_c_double) không kiểm tra của tôi cho is.nan.

+2

Bạn có biết rằng '1_c_double' là một số nguyên không? Sau khi nhận ra rằng bạn sẽ không tìm thấy thất bại mà thú vị hơn nữa. Dòng đầu tiên của bạn có thể chỉ là 'thực (loại = c_double), tham số :: ONE = 1' và nó sẽ thực hiện tương tự. Xem câu trả lời của tôi cho cú pháp thích hợp cho thực tế. –

+2

Vì vậy, cuối cùng bạn chỉ có thể rút ngắn nó thành 'thực (c_double), tham số :: NAN = TRANSFER (z'7FF0000000000001 ', 1._c_double)' hoặc 'thực (c_double), tham số :: NAN = TRANSFER (9218868437227405313_c_int64_t, 1._c_double) ' –

+0

@VladimirF, Cảm ơn bạn. – Avraham

Các vấn đề liên quan