From 6210222e4ee85a81a8799cd4b9b0756aa1da73b0 Mon Sep 17 00:00:00 2001 From: saikarna913 Date: Sat, 30 Nov 2024 11:05:46 +0530 Subject: [PATCH 1/3] Create Floating_Point_Numbers_comparison.md --- .../Floating_Point_Numbers_comparison.md | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 source/learn/Floating_Point_Numbers_comparison.md diff --git a/source/learn/Floating_Point_Numbers_comparison.md b/source/learn/Floating_Point_Numbers_comparison.md new file mode 100644 index 00000000000..5324e396cf2 --- /dev/null +++ b/source/learn/Floating_Point_Numbers_comparison.md @@ -0,0 +1,77 @@ +# Floating-Point Tolerance and Precision in Fortran + +Floating-point numbers like `0.1` cannot be represented exactly in binary because their binary form is infinite and repeating. Due to the limited precision of floating-point formats (like 32-bit or 64-bit), these numbers are rounded off to fit within the constrained number of bits. +This rounding can lead to small errors in representation and calculations. + +To ensure reliable comparisons, it is better to use **tolerance** to check whether two numbers are close enough rather than comparing them directly. + +## Handling Floating-Point Comparisons + +Here’s an example of how to use a tolerance value in Fortran: + +### Example: Using Tolerance +```fortran +real(dp) :: tol +tol = 10 * epsilon(1.0_dp) + +real(dp), parameter :: tol = 1.0e-10_dp +if (abs(x - y) < tol) then + print *, "Effectively Equal" +else + print *, "Not Equal" +end if +``` + +In this example: +- The **tolerance** value is derived using either `epsilon()` or a manually defined small value. +- Instead of checking `x == y`, we compare the absolute difference `abs(x - y)` to the tolerance. + +--- + +## Avoiding Floating-Point Precision Issues + +Sometimes, directly incrementing floating-point numbers can cause cumulative rounding errors. +Instead, use **integer iterators** and convert them to floating-point values within the loop. + +### Example: Using Integer Iterators +```fortran +integer :: i +real(dp) :: step, value +step = 0.1_dp + +do i = 0, 10 + value = i * step + print *, value +end do +``` + +In this example: +- The step size is defined as `0.1` in double precision. +- The loop uses integers (`i`) to avoid compounding errors when iterating. + +--- + +## Why Use Tolerance? + +Due to rounding errors, numbers like `0.1 + 0.2` may not exactly equal `0.3`. Direct comparisons fail in such cases: +```fortran +if (a + b == c) then + print *, "Equal" +else + print *, "Not Equal" +end if +``` +Instead, use a tolerance to make approximate comparisons: +```fortran +if (abs((a + b) - c) < tol) then + print *, "Approximately Equal" +else + print *, "Not Equal" +end if +``` + +--- + + + + From 9ee378be0a1ea97f3fb72c37b26f0768544b2a5b Mon Sep 17 00:00:00 2001 From: saikarna913 Date: Sat, 30 Nov 2024 11:11:35 +0530 Subject: [PATCH 2/3] Update learning.yml --- data/learning.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/data/learning.yml b/data/learning.yml index eaa2cbf8ae1..6febd16f995 100644 --- a/data/learning.yml +++ b/data/learning.yml @@ -22,6 +22,11 @@ books: - link: /learn/quickstart/organising_code - link: /learn/quickstart/derived_types + - title: Floating Point Numbers comparison + description: Learn how to handle rounding errors in floating-point numbers, use them in if and for loops, and make robust comparisons using tolerance in Fortran. + category: Getting started + link: /learn/Floating_Point_Numbers_comparison + - title: Building programs description: How to use the compiler to build an executable program category: Getting started From 27ab52f1477b04a0e24b7c18d42c3e5d411958dd Mon Sep 17 00:00:00 2001 From: saikarna913 Date: Sat, 7 Dec 2024 00:29:16 +0530 Subject: [PATCH 3/3] Update source/learn/Floating_Point_Numbers_comparison.md Co-authored-by: ZUO Zhihua --- source/learn/Floating_Point_Numbers_comparison.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/learn/Floating_Point_Numbers_comparison.md b/source/learn/Floating_Point_Numbers_comparison.md index 5324e396cf2..cde8ca6a7b8 100644 --- a/source/learn/Floating_Point_Numbers_comparison.md +++ b/source/learn/Floating_Point_Numbers_comparison.md @@ -12,13 +12,12 @@ Here’s an example of how to use a tolerance value in Fortran: ### Example: Using Tolerance ```fortran real(dp) :: tol -tol = 10 * epsilon(1.0_dp) - -real(dp), parameter :: tol = 1.0e-10_dp +tol = 10 * epsilon(1.0_dp) ! epsilon returns the smallest number such that 1.0 + epsilon > 1.0 + if (abs(x - y) < tol) then - print *, "Effectively Equal" + print *, "Effectively Equal" else - print *, "Not Equal" + print *, "Not Equal" end if ```