Question

En mathématiques la (1 + sqrt(2))^2 = 3 + 2*sqrt(2) identité est vraie. Mais en virgule flottante (IEEE 754, en utilisant une précision unique à savoir 32 bits) calculs il n'est pas le cas, comme sqrt(2) n'a pas une représentation exacte en binaire.

Il en va de l'aide d'une valeur approximative de sqrt(2) fournir des résultats différents pour les côtés gauche et droit? Si oui, pourquoi? Est-ce que la valeur approximative au carré de réduire de manière significative la précision?

Laquelle des expressions équivalentes donne alors le résultat le plus précis?

Était-ce utile?

La solution

Cette identité arrive à tenir lorsque calculé comme écrit en double précision IEEE-754. Voici pourquoi:

La racine carrée de deux arrondies correctement à double précision est:

sqrt(2) = 0x1.6a09e667f3bcd * 2^0

(J'utilise hexadécimal ici parce que les représentations sont plus net, et la traduction dans le format IEEE754 est beaucoup plus facile). Par deux est la multiplication exacte à virgule flottante binaire si aucun débordement, comme dans ce cas ici, donc:

2*sqrt(2) = 0x1.6a09e667f3bcd * 2^1

Lorsque nous ajoutons trois, nous obtenons:

3 + 2*sqrt(2) = 0x1.7504f333f9de68 * 2^2

Ceci, cependant, est pas un nombre double précision représentable (il est un peu trop large), de sorte que le résultat est arrondi au nombre représentable le plus proche. Il arrive que cette valeur est exactement à mi-chemin entre deux nombres représentables, donc nous choisissons celui avec un zéro bit de fuite:

3 + 2*sqrt(2) = 0x1.7504f333f9de6 * 2^2

De l'autre côté du calcul. Lorsque l'on ajoute un à la racine carrée à double précision de deux, nous obtenons:

1 + sqrt(2) = 0x1.3504f333f9de68 * 2^1

Il est également un cas à mi-chemin exact entre des nombres double précision représentables, et encore, il est arrondi au plus proche «même » nombre représentable:

1 + sqrt(2) = 0x1.3504f333f9de6 * 2^1

Lorsque cette valeur est carré, le résultat est:

(1 + sqrt(2))*(1 + sqrt(2)) = 0x1.7504f333f9de599cacbc97eaa4 * 2^2

Ce qui est pas un nombre double précision représentable soit. Celui-ci est pas un cas à mi-chemin exact, il arrondit simplement au nombre représentable le plus proche, qui est:

(1 + sqrt(2))*(1 + sqrt(2)) = 0x1.7504f333f9de6 * 2^2

Résumé: Le calcul de cette valeur de deux façons différentes engage deux séquences différentes de l'arrondissement, mais le résultat final est le même. Nous ne avons examiné le calcul en double précision, cependant; ce ne peut être le cas lorsque le calcul est effectué en utilisant différents types arithmétiques.

En général, cependant, le 3 + 2*sqrt(2) d'expression devrait être devrait être plus précis (dans les cas où ils diffèrent), car il encourt seulement deux arrondis (la racine carrée et l'add) pour tout binaire de type IEEE-754, alors que (1 + sqrt(2))*(1 + sqrt(2)) subit trois arrondis (racine carrée, ajouter et multiplier). Il convient également de noter que la différence entre les deux sera au plus un ou deux bits, et est probablement négligeable à vos besoins.

Autres conseils

Puisque même 0.1 + 0.2 != 0.3 vous ne devriez pas compter sur ces égalités complexes pour tenir des nombres à virgule flottante de précision limitée.

ils sont Puisque les nombres sont arrondis à CONSERVE un certain nombre de décimales binaires pressera pas si le nombre (comme 0,1) aurait une infinité de chiffres binaires. Par conséquent aussi les résultats des calculs avec ces chiffres ne seront pas exactes, et de petites différences au résultat exact d'un calcul sont attendus.

  

Il en va de l'aide d'une valeur approximative de sqrt (2) fournir des résultats différents pour les côtés gauche et droit? Si oui, pourquoi?

Mathématiquement, cette égalité ne fonctionne que à cause d'une relation exacte entre ces chiffres (il doit faire avec des longueurs des côtés d'un triangle). Si vous ajoutez sous la forme fuzziness de représentation inexacte, l'égalité ne l'est plus. L'égalité est une proposition binaire, la question ne soit plus « qui a raison », mais plutôt « est cette relation vrai du tout? ». Et la réponse est: « Non, ce n'est pas plus vrai ».

  

Est-ce la valeur approximative au carré de réduire de manière significative la précision?

Chaque opération sur deux valeurs à virgule flottante est susceptible de réduire leur exactitude. Un sous-ensemble très petit nombre d'opérations pour certains numéros - ceux avec des représentations binaires exactes -. Peut être garantie de ne pas aggraver la précision

En général, j'utilise [(1 + sqrt (2)) ^ 2] - [3 + 2 * sqrt (2)] <0,00001 pour tester l'égalité dans ces conditions (bien sûr, pour certains cas, je ne pas tenir compte de cette utilisation)

Y at-il une meilleure façon?

commentaires sont appréciés:)

Méfiez-vous les gars, en se fondant uniquement sur la différence absolue peut causer des problèmes. Il travaille pour un petit nombre d'environ 1, qui a assez de points décimaux pour pouvoir varier en fonction 1E-5 ou ce que vous utilisez. Mais pensez à un plus grand nombre. Leurs chiffres doivent être stockés dans un espace limité (mantisse). Et seuls les chiffres les plus significatifs sont stockés. Qu'est-ce que ça veut dire? Qu'il n'y a pas d'espace laissé à des chiffres de magasin qui permettrait de mesurer les différences comme 1E-5!

enveloppait, il est préférable d'utiliser la comparaison absolue et relative en même temps.

bool equal(float a, float b)
{
    if (abs(a - b) < eps)
        return true;
    if (abs(a - b) / max(abs(a), abs(b)) < eps)
        return true;
    return false;
} 

Regardez le bon côté: Si vous êtes au travail que l'équation pour éliminer les sqrts, alors puisque vous traitez avec des nombres entiers de taille raisonnable, l'équation sera exacte à virgule flottante;)

Incorrections sont généralement associés à des nombres qui nécessitent des fractions décimales (autres que les puissances de 0,5 et 0,2) à représenter.


Pour répondre à une autre partie de votre question: Non, le represenatation de sqrt(2) est en effet le même des deux côtés. Les erreurs (et les différences) ne sont pas introduites jusqu'à ce que vous commencez à appliquer (différentes) opérations à ce même numéro sur les deux côtés. Ajout de 1 par rapport à la multiplication par 2, etc

La personne qui a défini le comparateur d'égalité pour les flotteurs en C ++ doit être tourné:>. De nombreuses langues raisonnables (comme SML) ne disposent pas d'un opérateur de comparaison pour les flotteurs. J'utilise habituellement le code suivant:

template < typename T >
inline bool equals( T x, T y, T precision = std::numeric_limits<T>::epsilon() ) 
{
    return abs( x - y ) <= precision;
}

Note: abs est également une fonction ici basé sur un modèle, par défaut epsilon est stocké à l'extérieur. Les égaux dans la comparaison est destiné à mes fins.

En double précision, (1 + sqrt(2))^2 = 3 + 2*sqrt(2) semble tenir. Voir code C .

Je vais jeter encore une idée -

Oui, il est vrai, que l'égalité exacte des nombres réels est un concept vide de sens dans la programmation informatique.

Mais il est vrai aussi que l'égalité exacte des nombres réels est un concept vide de sens dans notre réalité physique.

Entiers dans notre réalité physique sont le résultat du dépouillement. nombres réels dans notre réalité physique sont le résultat de la mesure. Et toutes les mesures comprennent des erreurs. Dire que deux mesures physiques ont exactement la même valeur est un non-sens. Au mieux, deux mesures physiques, arrondies à un certain niveau de précision approprié à la précision que la mesure est capable, sont égaux.

Lorsque vous mesurez la longueur d'un crayon avec une règle, vous obtenez une longueur au plus proche 16e de pouce. Lorsque vous mesurez avec une paire d'étriers, vous obtenez une longueur 1000e de pouce. les mesures du monde réel comprennent toujours ce genre de l'arrondissement. Lorsque vous simulez des mesures du monde réel dans un programme informatique, vous devez faire la même chose.

L'égalité des nombres réels est un concept significatif que pour les mathématiciens. (Et même là, il est un autre, et concept plus complexe, que l'égalité des entiers).

  

sqrt (2) n'a pas une représentation exacte en binaire.

sqrt (2) ne présente pas une représentation exacte en décimal, hex, ou tout autre système de base n soit; il est un nombre irrationnel.

La seule représentation exacte de sqrt (2) est sqrt (2). Or, comme une solution à l'équation x 2 = 2.

Lorsque l'on compare les valeurs à virgule flottante, je trouve qu'il est préférable de comparer la valeur absolue de la différence à une tolérance donnée. Vous pouvez toujours compter sur cela.

  

Il en va de l'aide d'une valeur approximative de sqrt (2) fournir des résultats différents pour les côtés gauche et droit? Si oui, pourquoi? Est-ce que la valeur approximative au carré de réduire de manière significative la précision?

l'addition et la multiplication ont à la fois approximation d'erreur. la multiplication est empirique, surtout quand il est imbriqué.

Ce qui suit est pas une représentation précise, mais il aide à comprendre mon point:

example of addition:
(float1 * float2 + float3)
float1 * float2 + float3 + mult_approximation + add_approximation

example multiplication
(float1 * (float2 + float3))
(float1 * (float2 + float3 + add_apporiximation)
float1 * (float2 + float3) + add_approximation * float1 + mult_approximation

Il est parce que représentant des fonctions continues (infinies) comme sqrt (x) ne peut se faire sur une machine d'état discret (fini) exactement. Au lieu de cela sont traduites fonctions continues aux fonctions discrètes via l'extension de la série Taylor de 0 à n, où n est le nombre le plus élevé que vous pouvez représenter (dans ce cas, 2 ^ 32). Parce que vous ne pouvez pas prendre la somme de 0 à l'infini sur un ordinateur, vous vous retrouvez avec une suite d'erreur. Cette erreur peut être calculée afin que vous puissiez déterminer à quel point votre fonction discrète est la fonction continue.

Pour plus d'informations et de jolies représentations TeX des équations impliquées: http://en.wikipedia.org/wiki/Taylor_series

en général deux côtés vont vous donner des résultats différents. mathématiques à virgule flottante ne satisfait pas la propriété commutative et associés. il y a un certain nombre de facteurs impliqués, y compris les options du compilateur et du matériel.

pour votre équation, vous pouvez probablement trouver de quel côté est plus précis (je pense multiplié côté), mais il ne va pas tenir en général, si vous décidez d'utiliser des valeurs différentes, à savoir d'un côté peut être plus précis pour certaines valeurs , tandis que l'autre côté est plus précise pour d'autres valeurs.

équerrage ne devrait pas affecter significativement les résultats dans votre cas.

Étonnamment, si pour une raison quelconque, vous besoin d'une représentation précise des nombres non rationnels (indice: vous ne probablement pas), il y a quelque chose que vous pouvez faire: suite arithmétique des fractions. L'idée va à 1972, et est due à la super-pirate Bill Gosper - google it up. Soit dit en passant, les aspects plus avancés de cette idée sont une question de recherche en cours en mathématiques; voir par exemple cet article .

En général, les opérations en virgule flottante sont exactes jusqu'à FLT_EPSILON, à savoir, à l'intérieur du bit le moins significatif, ce qui pour les flotteurs IEEE 32 bits est 2 -23 .

Voir aussi: Wasn » t la précision type Double de 15 chiffres en C #?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top