On 2005-02-25 12:58:55 +0100, christianwtd wrote:
> Je ne pensais pas faire avancer le schmilblic dans cette discussion. De 
> fait il avance peu. Ce qu'il manque, mais je n'ai peut-être pas sû 
> trouver l'info, c'est surtout des renseignements sur les modes de calculs.
> Si on connais le nombre d'octets et les différents modes (entiers, 
> décimales) de calculs, on doit pouvoir définir à l'avance le degré de 
> précision des calculs. C'est un élément absent, dommage.

J'ai recherché un peu sur le site d'OpenOffice (recherche sur
"rounding"), et je suis tombé là-dessus:

http://sc.openoffice.org/servlets/ReadMsg?listName=dev&msgNo=1316

qui dit:

------------------------------------------------------------------------
[...]

It's a bit different. A result that's almost 1.1 is kept as-is, but when 
compared to a "real" 1.1, the numbers are treated as equal if they are 
very close.

rtl::math::approxEqual (from sal/inc/rtl/math.hxx) is used for that. It 
doesn't work when comparing to 0, so additions and subtractions have to 
be treated the same way (approxAdd, approxSub). These methods are used 
throughout the function implementations.

Niklas
------------------------------------------------------------------------

J'ai regardé dans le source, et effectivement, approxEqual() est
utilisée un peu partout dans "sal/inc/rtl/math.hxx". En gros, deux
nombres a et b sont considérés comme égaux si |a - b| < 2^(-48) |a|.
À partir de là, il y a une fonction d'addition ApproxAdd(a, b) qui
renvoie 0 exactement si approxEqual(a, -b) est vrai, etc.

Ceci doit expliquer pourquoi avec OpenOffice, 2.73 / 2 donne 1.37
(avec arrondi à 2 décimales), alors qu'en C, on obtient 1.36 (car
2.73 converti en binaire donne une valeur un peu inférieure, donc
la division par 2 donne une valeur un peu inférieure à 1.365).

Maintenant, si je reprends l'exemple qui avait été donné initialement:

  A1: 123456,78
  B1: =(A1-ENT(A1))*100
  C1: =ENT(B1)

A1 est converti de manière interne en binaire (valeur approchée à
2^(-53) près environ, car c'est de la double précision IEEE qui est
utilisée).

Pour B1, on commence par calculer A1 - ENT(A1). Ces deux nombres
sont très proches; on parle de « cancellation ». Le résultat est
petit par rapport aux nombres de départ (0,78 vs 123456), et bien
que cette soustraction se fasse exactement en base 2, l'erreur
relative (en tenant compte de l'erreur de départ due à la conversion
de 123456,78 en base 2) est beaucoup plus grande. B1 a ainsi une
valeur très proche de 78, mais à cause de la cancellation, l'erreur
relative est supérieure à 2^(-48).

Dans B1, 78 est affiché, car l'arrondi (au plus près) à 2 décimales
donne 78,00.

Mais pour C1, la fonction approxEqual() utilisée dans approxFloor()
détecte que la valeur est différente de 78, car l'erreur relative
est supérieure à 2^(-48). Donc c'est 77 qui est affiché.

Note: ce 2^(-48) est en dur dans le code d'OpenOffice; ce n'est pas
configurable.

À ce propos, le logiciel Mathematica a une approche différente: il
garde la trace d'une estimation de la précision à chaque calcul. Cf

  http://documents.wolfram.com/mathematica/book/section-3.1.5

Maintenant que ce soit la méthode d'OpenOffice ou la celle de
Mathematica, cela ne résout pas tous les problèmes et les résultats
ne sont pas du tout garantis. Pour du calcul scientifique, ce n'est
pas terrible, car on ne sait pas trop ce qui se passe en interne.

-- 
Vincent Lefèvre <[EMAIL PROTECTED]> - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / SPACES project at LORIA

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Répondre à