Kayan Noktalı Sayıların Neden Duyarlık Kaybedebileceği

Kayan nokta ondalık değerleri genellikle tam ikili gösterime sahip değildir. Bu, CPU'nun kayan nokta verilerini nasıl temsil ettiğiyle ilgili bir yan etkidir. Bu nedenle, duyarlık kaybı yaşayabilirsiniz ve bazı kayan nokta işlemleri beklenmeyen sonuçlara neden olabilir.

Bu davranış aşağıdakilerden birinin sonucudur:

  • Ondalık sayının ikili gösterimi tam olmayabilir.

  • Kullanılan sayılar arasında bir tür uyuşmazlığı vardır (örneğin, float ve double karışımı).

Çoğu programcı, davranışı çözmek için değerin gerekenden büyük veya daha küçük olduğundan emin olur ya da duyarlığı koruyacak bir İkili Kodlanmış Ondalık (BCD) kitaplığı alır ve kullanır.

Kayan nokta değerlerinin ikili gösterimi, kayan nokta hesaplamalarının duyarlığını ve doğruluğunu etkiler. Microsoft Visual C++ IEEE kayan nokta biçimini kullanır.

Örnek

// Floating-point_number_precision.c
// Compile options needed: none. Value of c is printed with a decimal
// point precision of 10 and 6 (printf rounded value by default) to
// show the difference
#include <stdio.h>

#define EPSILON 0.0001   // Define your own tolerance
#define FLOAT_EQ(x,v) (((v - EPSILON) < x) && (x <( v + EPSILON)))

int main() {
   float a, b, c;

   a = 1.345f;
   b = 1.123f;
   c = a + b;
   // if (FLOAT_EQ(c, 2.468)) // Remove comment for correct result
   if (c == 2.468)            // Comment this line for correct result
      printf_s("They are equal.\n");
   else
      printf_s("They are not equal! The value of c is %13.10f "
                "or %f",c,c);
}
They are not equal! The value of c is  2.4679999352 or 2.468000

Açıklamalar

EPSILON için, float için 1,192092896e-07F olarak tanımlanan FLT_EPSILON sabitlerini veya çift için 2,2204460492503131e-016 olarak tanımlanan DBL_EPSILON kullanabilirsiniz. Bu sabitler için float.h eklemeniz gerekir. Bu sabitler, x+1.0'ın 1,0'a eşit olmaması için en küçük pozitif x sayısı olarak tanımlanır. Bu çok küçük bir sayı olduğundan, çok büyük sayılar içeren hesaplamalar için kullanıcı tanımlı tolerans kullanmalısınız.

Ayrıca bkz.

Kodunuzu İyileştirme