How to Handle Floating Point Errors in Fortran90 Real Number Calculations

In summary, the conversation discusses an individual's attempts to write a code that calculates certain values. However, the results are not accurate due to the use of single precision and the way numbers are stored in binary format. Suggestions are made to use double precision and formatted output to improve the accuracy of the calculations. The conversation also touches on the topic of why computers cannot always perform simple arithmetic accurately. Ultimately, the individual finds the error in their code and thanks those who offered assistance.
  • #1
abdulsulo
14
0
Hello guys I am trying to write a code which is below;

But my results seems to be fairly wrong.

I noticed some of my real numbers are not what I assigned them. For example Ks shows on the watch window as 9.9999999E-5.

How can I fix such situation?

Fortran:
program hw1
  
    REAL:: G,DVIS,Ks, EPS,LENGTH,D,Vs,Re,Vi,V0,FFACT,DELt,I,Vi1,H,T,PHO
  
    G=9.81
    D=0.3
    H=8
    Ks=1E-4
    T=60
    DVIS=0.001
    PHO=1000
    EPS=0.01
    DELt=0.02
    write(*,*) Ks
    write(*,*) G
    write(*,*) H
    write(*,*) T
    write(*,*) DVIS
    write(*,*) PHO
    write(*,*) EPS
    write(*,*) DELt
    WRITE(*,*) 'INPUT CYLINDER DIAMETER'
    READ(*,*) D
    WRITE(*,*) 'LENGTH'
    READ(*,*) LENGTH
  
    IF (LENGTH==50) THEN
        Vs=6.586
    ELSE IF (LENGTH==100) THEN
        Vs=5.00
    ELSE IF (LENGTH==200) THEN
        Vs=3.669
    ELSE IF (LENGTH==500) THEN
        Vs=2.36
    END IF
    write(*,*) Ks
    Re=PHO*Vs*D/DVIS
    write(*,*) Re
    FFACT=0.25/((log((Ks/(3.7*D))+(5.74/Re**0.9)))**2)   
    write(*,*) FFACT
    Vi=0
    write(*,*) Vi
    DO I=0.02, 200, 0.02
        if (I==0.02) THEN
            Vi1=Vi+(DELt*(H)*G/LENGTH)
            Vi=Vi1
            write(*,*) Vi1
        ELSE
        Re=PHO*Vi*D/DVIS
        FFACT=0.25/((log((Ks/(3.7*D))+(5.74/Re**0.9)))**2)
        Vi1=Vi+(DELt*(H-((1+(FFACT*LENGTH/D))*((Vi**2)/(2*G))))*G/LENGTH)
        Vi=Vi1
        write(*,*) Vi1
        end if
    end do
  
    pause
  
end program
<<Moderator's note: added code tags>>
 
Technology news on Phys.org
  • #3
I read and tried to understand. But it seems there are no solutions for this? Am I wrong?
 
  • #4
If you want higher precision, then use
Fortran:
REAL(KIND(1d0)) :: G,DVIS,Ks, EPS,LENGTH,D,Vs,Re,Vi,V0,FFACT,DELt,I,Vi1,H,T,PHO
to get double precision. On modern computer, single precision should not be used anyway.
 
Last edited by a moderator:
  • Like
Likes abdulsulo
  • #6
Notice that the printed values of K are actually very close to the number you set it to. 1E-4 and 9.9999999E-5 only differ by 0.000000000001 = 1E-12.
Number fractions on the computer are stored in binary and will not be exactly as you set them in base 10. The formats mentioned by others above will make them appear the same. If you need more accuracy, you should use a variable type for K that will keep more significant digits.
 
  • Like
Likes abdulsulo
  • #7
FactChecker said:
Number fractions on the computer are stored in binary and will not be exactly as you set them in base 10.
... and some will not be exactly as you set them.

Fractions that are linear combinations of 1/2, 1/4, 1/8, 1/16, and so on, are stored in exact form. Fractions such as 1/5 and 1/10, that have nice, compact forms in base-10 (i.e., 1/5 = .2, 1/10 = .1), but their representations as binary fractions have patterns that repeat endlessly, and so they are not stored in exact form.
 
  • Like
Likes abdulsulo
  • #9
Thank you all for kind insights. Now I got to read through articles that you linked and try to find solution to my problem.
 
  • #10
I am trying to make simple calculation of below;
Vi= 6.586542
Vs=6.586000

The program finds a as 6.554608 from below equation. How is this possible?
a=ABS(Vi-Vs)

EDİT: I found my error. Thank you for your interest.
 
Last edited:

What is a real number in Fortran90?

A real number in Fortran90 is a data type that represents numbers with decimal points. It includes both floating-point numbers (numbers with a decimal point and an exponent) and fixed-point numbers (numbers with a decimal point and a fixed number of digits after the decimal point).

How do I declare a real number in Fortran90?

To declare a real number in Fortran90, you can use the "real" keyword followed by the desired precision (i.e. the number of digits after the decimal point). For example, "real :: x" will declare a real number named "x" with default precision. You can also specify the precision using the "kind" keyword, such as "real(kind=8) :: y" to declare a double-precision real number named "y".

What is the difference between single-precision and double-precision real numbers in Fortran90?

Single-precision real numbers in Fortran90 have a precision of 7 digits, while double-precision real numbers have a precision of 15 digits. This means that double-precision numbers can represent larger and more precise values than single-precision numbers, but they also require more memory to store.

Can I perform mathematical operations on real numbers in Fortran90?

Yes, you can perform various mathematical operations on real numbers in Fortran90, such as addition, subtraction, multiplication, and division. Fortran90 also supports more advanced mathematical functions, such as trigonometric and logarithmic functions, that can be applied to real numbers.

How do I convert a real number to an integer in Fortran90?

To convert a real number to an integer in Fortran90, you can use the "int" function, which truncates the value of the real number to the nearest integer. For example, "int(3.8)" will return the integer value of 3. You can also use the "nint" function, which rounds the value of the real number to the nearest integer. For example, "nint(3.8)" will return the integer value of 4.

Similar threads

  • Programming and Computer Science
Replies
11
Views
2K
  • Atomic and Condensed Matter
Replies
3
Views
876
  • Programming and Computer Science
Replies
1
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
1
Views
2K
Back
Top