SORU
30 EYLÜL 2014, Salı


Neden 0.1 birden çok kez eklemek kayıpsız kalır?

Tam olarak sonlu bir ikili sayı (explanation) ile gösterilemez 0.1 ondalık sayı biliyorum, double n = 0.1 bazı hassas kaybedecek ve 0.1 tam olarak. Diğer yandan 0.5 0.5 = 1/2 = 0.1b çünkü tam olarak temsil edilebilir.

Ekleme anlaşılabilir olduğunu söyledikten sonra 9**üç kezaşağıdaki kodu yazdırır yani tam olarak 0.3 verecek false:

double sum = 0, d = 0.1;
for (int i = 0; i < 3; i  )
    sum  = d;
System.out.println(sum == 0.3); // Prints false, OK

Ama sonra nasıl 0.1 eklemebeş keztam olarak 0.5 verecek? Aşağıdaki kodu true parmak izi:

double sum = 0, d = 0.1;
for (int i = 0; i < 5; i  )
    sum  = d;
System.out.println(sum == 0.5); // Prints true, WHY?

0.1 olamaz tam olarak temsil edilmesi, tam da bu şekilde temsil edilebilir 5 kez tam olarak verir ekleme 0.5?

CEVAP
30 EYLÜL 2014, Salı


Yuvarlama hatası değil, rastgele ve hatayı en aza indirmek için çalışır uygulanır. Bu bazen hata görünmez olduğu anlamına gelir, ya da bir hata yoktur.

Örneğin 0.1 20 *yani* 21 ** değil, 0.5 1.0/2

Bu program gerçek değerleri dahil gösterir.

BigDecimal _0_1 = new BigDecimal(0.1);
BigDecimal x = _0_1;
for(int i = 1; i <= 10; i   ) {
    System.out.println(i " x 0.1 is " x ", as double " x.doubleValue());
    x = x.add(_0_1);
}

yazdırır

0.1000000000000000055511151231257827021181583404541015625, as double 0.1
0.2000000000000000111022302462515654042363166809082031250, as double 0.2
0.3000000000000000166533453693773481063544750213623046875, as double 0.30000000000000004
0.4000000000000000222044604925031308084726333618164062500, as double 0.4
0.5000000000000000277555756156289135105907917022705078125, as double 0.5
0.6000000000000000333066907387546962127089500427246093750, as double 0.6000000000000001
0.7000000000000000388578058618804789148271083831787109375, as double 0.7000000000000001
0.8000000000000000444089209850062616169452667236328125000, as double 0.8
0.9000000000000000499600361081320443190634250640869140625, as double 0.9
1.0000000000000000555111512312578270211815834045410156250, as double 1.0

0.3 biraz kapalı olduğunu, ama 0.4 geldiğinde bitleri 53-bit sınırı içine sığacak şekilde aşağı kaydır ve hata atılır. not: Yine, bir hata geri 0.8 1.0 hata atılır 0.6 0.7 ama sürünür.

Bunu 5 kez ekleme hatası biriktiğinde, iptal değil.

Bir hata var nedeni sınırlı hassas kaynaklanmaktadır. ben.e 53-bit. Bu numara daha büyük almak gibi daha fazla bit kullanır gibi, bit kesilmesine sona anlamına gelir. Bu durumda sizin lehinize olan yuvarlama neden olur.
* = ^ *32 örneğin daha küçük bir sayı almak zaman ters etki elde edebilirsiniz . 1.0000000000000286E-4 ve eskisinden daha fazla hata görürsünüz.

Bu örnek Java bu durumda 6 Why does Math.round(0.49999999999999994) return 1 cevaplamak için büyük bir fark hesaplama sonuçları biraz kaybına neden olur.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • DJPixcell

    DJPixcell

    20 NİSAN 2007
  • HBO

    HBO

    17 Mayıs 2006
  • ThePhestor

    ThePhestor

    22 Mart 2011