User Manual 4.3 Double Comparisons : Différence entre versions

De Wiki
Aller à : navigation, rechercher
(Contenu remplacé par « Category:User_Manual_4.3_Mathematics »)
 
Ligne 1 : Ligne 1 :
 +
__NOTOC__
 +
== Introduction ==
 +
=== Scope ===
 +
The « Comparators » class contains static methods to perform relative comparisons of doubles.
 +
 +
=== Javadoc ===
 +
The Comparators class is available in the <code>package fr.cnes.sirius.patrius.math.interval</code>.
 +
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| Library
 +
! scope="col"| Javadoc
 +
|-
 +
|Patrius
 +
|[{{JavaDoc4.3}}/fr/cnes/sirius/patrius/math/interval/package-summary.html Package fr.cnes.sirius.patrius.math.interval]
 +
|}
 +
 +
=== Links ===
 +
Some elements about the “equals” comparators previously proposed in the “MathUtils” class are described in the document “Comparing floating point numbers” by Bruce Dawson : [http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm].
 +
 +
=== Useful Documents ===
 +
None as of now.
 +
 +
=== Package Overview ===
 +
The doubles comparison issue is adressed through a single utility class, [{{JavaDoc4.3}}/fr/cnes/sirius/patrius/math/Comparators.html Comparators],  in the fr.cnes.sirius.patrius.utils package.
 +
 +
== Features Description ==
 +
=== Algorithms and espilon value ===
 +
The need here is to compare two values with a known maximum relative difference.
 +
 +
The “equals” comparators previously proposed in the “MathUtils” class are of two types :
 +
 +
* a simple absolute comparison using an epsilon
 +
* a more complex one, described in the document “Comparing floating point numbers” by Bruce Dawson (see the Links paragraph)
 +
 +
This last comparison makes more sense to compare real values and takes into account the precision issues due to the double type. It works as well with any exponent (high values or close to zero…), but the relative difference accepted between two equal doubles is uncontrolled, between 2.5e-16 and 1.25e-16 for a maxUlps of 1 (difference between two consecutive doubles).
 +
 +
 +
Here is proposed a new comparison method to control the maximum relative difference and still have a comparison that makes sense when computed.
 +
 +
=== The Comparators class ===
 +
The new comparison method is implemented in the Comparators class. Its simplified algorithm is described below with pseudo-code.
 +
 +
''x and y are two doubles.''
 +
 +
* '' IF x equals y in the Bruce Dawson’s way ''
 +
** ''=> Then the return is “TRUE” regardless to relative difference''
 +
* '' ELSE :''
 +
** ''=> IF the absolute relative difference is lower than the epsilon, then the return is “TRUE”''
 +
* ''ENDIF''
 +
 +
NB : the epsilon can be chosen by the user, eventually between 2.5e-16 and 1.25e-16 (min and max values for the relative difference in Bruce Dawson’s algorithm). In that case, the comparison becomes at worst uncontrolled and doesn’t make any sense : sometimes the epsilon will be used, sometimes not, without information to the user. If the chosen epsilon is lower than 1.25e-16, it becomes useless.
 +
 +
The default epsilon proposed is :
 +
 +
''Comparators.DOUBLE_COMPARISON_EPSILON'' = 1.0e-14
 +
 +
(two orders higher than the max relative difference between to consecutive doubles)
 +
 +
==== Using the Comparators class ====
 +
 +
The Comparators class provides the following static methods ''equal, lowerOrEqual, greaterOrEqual, lowerStrict, greaterStrict,'' for doubles comparison purposes.
 +
 +
Their returns are Booleans, in order to be used the same way as classical « > », « == »…
 +
 +
Code examples :
 +
 +
<syntaxhighlight lang="java">
 +
if (Comparators.equals(x, y, eps)) { } // epsilon given by the user
 +
if (Comparators.equals(x, y)) { }  // default epsilon
 +
if (Comparators.lowerOrEqual(x, y)) { }  // default epsilon
 +
</syntaxhighlight>
 +
 +
These comparisons are relative and use an epsilon value. Each method is duplicated, so the choice is given to use the default epsilon (''Comparators.DOUBLE_COMPARISON_EPSILON'') or any other value, by adding it to the method’s signature.
 +
 +
To respect the '''IEEE Standard 754''', a “NaN” is considered different to any other double, including “NaN” itself, and the positive and negative infinite values are considered only equal to themselves (see behaviour examples).
 +
 +
==== Examples of "equals" method behaviour (using default epsilon) : ====
 +
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| X
 +
! scope="col"| Y
 +
! scope="col"| |X-Y|/Y
 +
! scope="col"| MathUtils.equals result
 +
! scope="col"| Comparators.equals result
 +
|-
 +
|0.0
 +
|1.0e-300
 +
|1.0
 +
|false
 +
|false
 +
|-
 +
|1.25000000000000025
 +
|1.25
 +
|2.0e-16
 +
|false
 +
|true
 +
|-
 +
|1.0000000000000002
 +
|1.0
 +
|2.0e-16
 +
|true
 +
|true
 +
|-
 +
|1.0000000000000001e+300
 +
|1.0e+300
 +
|1.0e-16
 +
|true
 +
|true
 +
|-
 +
|1.0000000000000001e-300
 +
|1.0e-300
 +
|1.0e-16
 +
|true
 +
|true
 +
|-
 +
|1.000000000000001
 +
|1.0
 +
|1.0e-15
 +
|false
 +
|true
 +
|-
 +
|1.000000000000001e+300
 +
|1.0e+300
 +
|1.0e-15
 +
|false
 +
|true
 +
|-
 +
|1.000000000000001e-300
 +
|1.0e-300
 +
|1.0e-15
 +
|false
 +
|true
 +
|-
 +
|1.0000000000001
 +
|1.0
 +
|1.0e-13
 +
|false
 +
|false
 +
|-
 +
|1.0000000000001e+300
 +
|1.0e+300
 +
|1.0e-13
 +
|false
 +
|false
 +
|-
 +
|1.0000000000001e-300
 +
|1.0e-300
 +
|1.0e-13
 +
|false
 +
|false
 +
|-
 +
|NaN
 +
|NaN
 +
| -
 +
|false
 +
|false
 +
|-
 +
|NaN
 +
|Any other double
 +
| -
 +
|false
 +
|false
 +
|-
 +
|POSITIVE_INFINITE
 +
|POSITIVE_INFINITE
 +
| -
 +
|true
 +
|true
 +
|-
 +
|POSITIVE_INFINITE
 +
|Any other double
 +
| -
 +
|false
 +
|false
 +
|}
 +
 +
Notice the second and third lines : two pair of doubles with the same relative difference imply a “false” for the first, and a “true” for the second.
 +
 +
Using a relative epsilon allows us to stay coherent in any case.
 +
 +
 +
'''Beware :''' when realizing a comparison close to zero, you must think about the type of comparison needed. In order to perform comparison in the same way regardless to the exponents, our comparator considers a double with a very low exponent different to zero (first line of the example). In some cases, an absolute comparison with epsilon shall be needed (to compare the result of a computation to zero...).
 +
 +
== Getting Started ==
 +
{{specialInclusion prefix=$theme_sub section="GettingStarted"/}}
 +
 +
== Contents ==
 +
=== Interfaces ===
 +
None as of now.
 +
 +
=== Classes ===
 +
The only class is <code>fr.cnes.sirius.patrius.math.Comparators</code>.
 +
 +
{| class="wikitable"
 +
|-
 +
! scope="col"| Class
 +
! scope="col"| Summary
 +
! scope="col"| Javadoc
 +
|-
 +
|'''Comparators'''
 +
|Static comparison methods for real numbers
 +
|[{{JavaDoc4.3}}/fr/cnes/sirius/patrius/math/Comparators.html ...]
 +
|}
 +
 
[[Category:User_Manual_4.3_Mathematics]]
 
[[Category:User_Manual_4.3_Mathematics]]

Version actuelle en date du 28 mai 2019 à 09:04

Introduction

Scope

The « Comparators » class contains static methods to perform relative comparisons of doubles.

Javadoc

The Comparators class is available in the package fr.cnes.sirius.patrius.math.interval.

Library Javadoc
Patrius Package fr.cnes.sirius.patrius.math.interval

Links

Some elements about the “equals” comparators previously proposed in the “MathUtils” class are described in the document “Comparing floating point numbers” by Bruce Dawson : http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm.

Useful Documents

None as of now.

Package Overview

The doubles comparison issue is adressed through a single utility class, Comparators, in the fr.cnes.sirius.patrius.utils package.

Features Description

Algorithms and espilon value

The need here is to compare two values with a known maximum relative difference.

The “equals” comparators previously proposed in the “MathUtils” class are of two types :

  • a simple absolute comparison using an epsilon
  • a more complex one, described in the document “Comparing floating point numbers” by Bruce Dawson (see the Links paragraph)

This last comparison makes more sense to compare real values and takes into account the precision issues due to the double type. It works as well with any exponent (high values or close to zero…), but the relative difference accepted between two equal doubles is uncontrolled, between 2.5e-16 and 1.25e-16 for a maxUlps of 1 (difference between two consecutive doubles).


Here is proposed a new comparison method to control the maximum relative difference and still have a comparison that makes sense when computed.

The Comparators class

The new comparison method is implemented in the Comparators class. Its simplified algorithm is described below with pseudo-code.

x and y are two doubles.

  • IF x equals y in the Bruce Dawson’s way
    • => Then the return is “TRUE” regardless to relative difference
  • ELSE :
    • => IF the absolute relative difference is lower than the epsilon, then the return is “TRUE”
  • ENDIF

NB : the epsilon can be chosen by the user, eventually between 2.5e-16 and 1.25e-16 (min and max values for the relative difference in Bruce Dawson’s algorithm). In that case, the comparison becomes at worst uncontrolled and doesn’t make any sense : sometimes the epsilon will be used, sometimes not, without information to the user. If the chosen epsilon is lower than 1.25e-16, it becomes useless.

The default epsilon proposed is :

Comparators.DOUBLE_COMPARISON_EPSILON = 1.0e-14

(two orders higher than the max relative difference between to consecutive doubles)

Using the Comparators class

The Comparators class provides the following static methods equal, lowerOrEqual, greaterOrEqual, lowerStrict, greaterStrict, for doubles comparison purposes.

Their returns are Booleans, in order to be used the same way as classical « > », « == »…

Code examples :

if (Comparators.equals(x, y, eps)) { } // epsilon given by the user
if (Comparators.equals(x, y)) { }  // default epsilon
if (Comparators.lowerOrEqual(x, y)) { }  // default epsilon

These comparisons are relative and use an epsilon value. Each method is duplicated, so the choice is given to use the default epsilon (Comparators.DOUBLE_COMPARISON_EPSILON) or any other value, by adding it to the method’s signature.

To respect the IEEE Standard 754, a “NaN” is considered different to any other double, including “NaN” itself, and the positive and negative infinite values are considered only equal to themselves (see behaviour examples).

Examples of "equals" method behaviour (using default epsilon) :

X Y |X-Y|/Y MathUtils.equals result Comparators.equals result
0.0 1.0e-300 1.0 false false
1.25000000000000025 1.25 2.0e-16 false true
1.0000000000000002 1.0 2.0e-16 true true
1.0000000000000001e+300 1.0e+300 1.0e-16 true true
1.0000000000000001e-300 1.0e-300 1.0e-16 true true
1.000000000000001 1.0 1.0e-15 false true
1.000000000000001e+300 1.0e+300 1.0e-15 false true
1.000000000000001e-300 1.0e-300 1.0e-15 false true
1.0000000000001 1.0 1.0e-13 false false
1.0000000000001e+300 1.0e+300 1.0e-13 false false
1.0000000000001e-300 1.0e-300 1.0e-13 false false
NaN NaN - false false
NaN Any other double - false false
POSITIVE_INFINITE POSITIVE_INFINITE - true true
POSITIVE_INFINITE Any other double - false false

Notice the second and third lines : two pair of doubles with the same relative difference imply a “false” for the first, and a “true” for the second.

Using a relative epsilon allows us to stay coherent in any case.


Beware : when realizing a comparison close to zero, you must think about the type of comparison needed. In order to perform comparison in the same way regardless to the exponents, our comparator considers a double with a very low exponent different to zero (first line of the example). In some cases, an absolute comparison with epsilon shall be needed (to compare the result of a computation to zero...).

Getting Started

Modèle:SpecialInclusion prefix=$theme sub section="GettingStarted"/

Contents

Interfaces

None as of now.

Classes

The only class is fr.cnes.sirius.patrius.math.Comparators.

Class Summary Javadoc
Comparators Static comparison methods for real numbers ...