Je me retrouve souvent dans des situations où il est nécessaire de vérifier si la différence obtenue est supérieure à la précision de la machine. On dirait à cette fin R a une variable à portée de main: .Machine$double.eps
. Cependant, lorsque je me tourne vers le code source R pour obtenir des instructions sur l'utilisation de cette valeur, je vois plusieurs modèles différents.
Exemples
Voici quelques exemples tirés de la stats
bibliothèque:
t.test.R
if(stderr < 10 *.Machine$double.eps * abs(mx))
chisq.test.R
if(abs(sum(p)-1) > sqrt(.Machine$double.eps))
integrer.R
rel.tol < max(50*.Machine$double.eps, 0.5e-28)
lm.influence.R
e[abs(e) < 100 * .Machine$double.eps * median(abs(e))] <- 0
princomp.R
if (any(ev[neg] < - 9 * .Machine$double.eps * ev[1L]))
etc.
Des questions
- Comment peut - on comprendre le raisonnement derrière tous ces différents
10 *
,100 *
,50 *
etsqrt()
modificateurs? - Existe-t-il des directives sur l'utilisation
.Machine$double.eps
pour ajuster les différences en raison de problèmes de précision?
r
floating-point
rounding
precision
Karolis Koncevičius
la source
la source
double.eps
. Si vous effectuez plusieurs opérations sur un nombre à virgule flottante, votre tolérance aux erreurs doit également s'ajuster. C'est pourquoi all.equal vous donne untolerance
argument.Réponses:
La précision de la machine
double
dépend de sa valeur actuelle..Machine$double.eps
donne la précision lorsque les valeurs sont 1. Vous pouvez utiliser la fonction CnextAfter
pour obtenir la précision de la machine pour d'autres valeurs.La valeur ajoutée
a
à la valeurb
ne changera pasb
quanda
est la<=
moitié de la précision de la machine. Vérifier si la différence est plus petite que la précision de la machine<
. Les modificateurs peuvent prendre en compte les cas typiques de la fréquence à laquelle un ajout n'a pas montré de changement.Dans R, la précision de la machine peut être estimée avec:
Chaque
double
valeur représente une plage. Pour un ajout simple, la plage du résultat dépend de la réanimation de chaque somme et également de la plage de leur somme.Pour une plus grande précision, on
Rmpfr
pourrait utiliser.Au cas où il pourrait être converti en entier
gmp
pourrait être utilisé (ce qui est dans Rmpfr).la source
Définition d'une machine.eps: c'est la valeur la plus basse
eps
pour laquelle1+eps
n'est pas1
En règle générale (en supposant une représentation en virgule flottante avec la base 2):
Cela
eps
fait la différence pour la plage 1 .. 2,pour la plage 2 .. 4 la précision est
2*eps
et ainsi de suite.
Malheureusement, il n'y a pas de bonne règle empirique ici. Il est entièrement déterminé par les besoins de votre programme.
Dans R, nous avons all.equal comme méthode intégrée pour tester l'égalité approximative. Vous pourriez donc utiliser quelque chose comme
(x<y) | all.equal(x,y
)Google Mock dispose d'un certain nombre de comparateurs à virgule flottante pour les comparaisons à double précision, y compris
DoubleEq
etDoubleNear
. Vous pouvez les utiliser dans un matcher de tableau comme celui-ci:Mise à jour:
Les recettes numériques fournissent une dérivation pour démontrer que l'utilisation d'un quotient de différence unilatérale
sqrt
est un bon choix de taille de pas pour les approximations de différences finies de dérivés.Le site d'articles Wikipédia Recettes numériques, 3e édition, section 5.7, qui se trouve aux pages 229-230 (un nombre limité de pages vues est disponible sur http://www.nrbook.com/empanel/ ).
Cette arithmétique à virgule flottante IEEE est une limitation bien connue de l'arithmétique informatique et est discutée à plusieurs endroits:
.
dplyr::near()
est une autre option pour tester si deux vecteurs de nombres à virgule flottante sont égaux.La fonction a un paramètre de tolérance intégré:
tol = .Machine$double.eps^0.5
qui peut être ajusté. Le paramètre par défaut est le même que celui par défaut pourall.equal()
.la source
all.equal()
a aussi sa propre hypothèse comme tolérance par défautsqrt(double.eps)
- pourquoi est-ce la valeur par défaut? Est-ce une bonne règle à utilisersqrt()
?stats::
source R , et 2) quelles sont les lignes directrices; la réponse est assez mince. La seule phrase applicable semble être la référence de "Recettes numériques" à propos de sqrt () étant un bon défaut, ce qui est vraiment pertinent, je pense. Ou peut-être que je manque quelque chose ici.