Precision problems of real numbers in Fortran [dup

2019-01-12 11:27发布

问题:

This question already has an answer here:

  • Is floating point math broken? 28 answers

I've been trying to use Fortran for my research project, with the GNU Fortran compiler (gfortran), latest version, but I've been encountering some problems in the way it processes real numbers. If you have for example the code:

program test
implicit none

real :: y = 23.234, z

z = y * 100000
write(*,*) y, z

end program

You'll get as output:

23.23999    2323400.0 

I find this really strange. Can someone tell me what's exactly happening here? Looking at z I can see that y does retain its precision, so for calculations that shouldn't be a problem I suppose. But why is the output of y not exactly the same as the value that I've specified, and what can I do to make it exactly the same?

回答1:

This is not a problem - all you see is floating-point representation of the number in the computer. The computer cannot handle real numbers exactly, but only approximations of them. A good read about this can be found here: What Every Computer Scientist Should Know About Floating-Point Arithmetic.



回答2:

Simply by replacing real with double precision, you can increase the number of significant decimal places from about six to about 15 on most platforms.



回答3:

The general issue is not limited to Fortran, but the representation of base 10 real numbers in another base of finite precision. This computer science question is asked many times here.

For the specifically Fortran aspects, the declaration "real" will likely give you a single precision floating point. As will expressing a constant as "23.234" without a type qualifier. The constant "100000" without a decimal point is an integer so the expression "y * 100000" is causing an implicit conversion of an integer to a real because "y" is a real variable.

For previous some previous discussions of these issues see Extended double precision , Fortran: integer*4 vs integer(4) vs integer(kind=4) and Is There a Better Double-Precision Assignment in Fortran 90?



回答4:

The problem here is not with Fortran, in fact it is not a problem at all. This is just a feature of floating-point arithmetic. If you think about how you would represent 23.234 as a 'single float' in binary, you would see that the number has to be saved to only so many decimals of precision.

The thing to remember about float point number is: numbers that look round and even in base-10 probably won't in binary.

For a brief overview of floating-point topics, check the Wikipedia article. And for a VERY thorough explanation, check out the canonical paper by Goldberg (PDF).