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

  • Joseph Hayhoe

    Joseph Hayho

    20 Mayıs 2010
  • steven johns

    steven johns

    11 Mart 2011
  • TheForgottenGamer1

    TheForgotten

    28 AĞUSTOS 2009