Pourquoi ai-je un résultat différent de std :: fmod et std :: rest

Dans l’exemple d’application ci-dessous, je calcule le rest de la virgule flottante en divisant 953 par 0.1 , à l’aide de std::fmod

Ce à quoi je m’attendais, c’est que depuis 953.0 / 0.1 == 9530 , ce std::fmod(953, 0.1) == 0

Je reçois 0.1pourquoi est-ce le cas?

Notez qu’avec std::remainder le résultat est correct.

C’est:

 std::fmod (953, 0.1) == 0.1 // unexpected std::remainder(953, 0.1) == 0 // expected 

Différence entre les deux fonctions:

Selon cppreference.com

  • std::fmod calcule ce qui suit:

exactement la valeur x - n*y , où n est x/y avec sa partie décimale tronquée

  • std::remainder calcule ce qui suit:

exactement la valeur x - n*y , où n est la valeur intégrale la plus proche de la valeur exacte x/y

Compte tenu de mes entrées, les deux fonctions devraient avoir la même sortie. Pourquoi n’est-ce pas le cas?

Application exemplaire:

 #include  #include  bool is_zero(double in) { return std::fabs(in) < 0.0000001; } int main() { double numerator = 953; double denominator = 0.1; double quotient = numerator / denominator; double fmod = std::fmod (numerator, denominator); double rem = std::remainder(numerator, denominator); if (is_zero(fmod)) fmod = 0; if (is_zero(rem)) rem = 0; std::cout << "quotient: " << quotient << ", fmod: " << fmod << ", rem: " << rem << std::endl; return 0; } 

Sortie:

 quotient: 9530, fmod: 0.1, rem: 0 

Bienvenue aux maths en virgule flottante. Voici ce qui se passe: un dixième ne peut pas être représenté exactement en binary, tout comme un tiers ne peut pas être représenté exactement en décimal. En conséquence, la division produit un résultat légèrement inférieur à 9530. Le fonctionnement au sol génère le nombre entier 9529 au lieu de 9530. Il ne rest que 0,1.

Parce que ce sont des fonctions différentes.

std::remainder(x, y) calcule le rest IEEE qui est x - (round(x/y)*y) où arrondi arrondit la moitié à même (donc notamment round(1.0/2.0) == 0 )

std::fmod(x, y) calcule x - trunc(x/y)*y . Lorsque vous divisez 953 par 0.1 vous pouvez obtenir un nombre légèrement inférieur à 9530; la troncature donne donc 9529. Le résultat obtenu est donc 953.0 - 952.9 = 0.1