2010-10-10 18 views
7

Bozuk bir şey mi var, ne olduğunu anlayamıyorum? çıkışı ileEn küçük artışla çift nasıl değiştirilir

static String getRealBinary(double val) { 
    long tmp = Double.doubleToLongBits(val); 
    StringBuilder sb = new StringBuilder(); 

    for (long n = 64; --n > 0; tmp >>= 1) 
     if ((tmp & 1) == 0) 
      sb.insert(0, ('0')); 
     else 
      sb.insert(0, ('1')); 

    sb.insert(0, '[').insert(2, "] [").insert(16, "] [").append(']'); 
    return sb.toString(); 
} 

public static void main(String[] argv) { 
    for (int j = 3; --j >= 0;) { 
     double d = j; 
     for (int i = 3; --i >= 0;) { 
      d += Double.MIN_VALUE; 
      System.out.println(d +getRealBinary(d)); 
     } 
    } 
} 

: tamsayı türleri gibi

2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000] 
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000] 
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000] 
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000] 
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000] 
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000] 
4.9E-324[0] [00000000000] [000000000000000000000000000000000000000000000000001] 
1.0E-323[0] [00000000000] [000000000000000000000000000000000000000000000000010] 
1.5E-323[0] [00000000000] [000000000000000000000000000000000000000000000000011] 
+4

Ne yapmaya çalışıyorsunuz? Sorun nedir? – Sjoerd

+0

Sorum şu: "En küçük artışla iki katı nasıl değiştirilir", ve bu benim başarısız olduğum çabam. – Margus

+1

neden sadece en küçük artış yapmak istiyorsanız bu bitleri düzenlemek değil, 1 ve 2 için başarısız olur, çünkü MIN_VALUE küçük (gerçekten küçük) yani 0 + gerçekten küçük = gerçekten küçük, ama 2+ gerçekten küçük ~ = 2 YÜKSELME noktası min_value, mümkün olduğu kadar uzak bırakılırken, ortada bir yerde, solu kaybeder. Farkın yapılacağı noktadan sonra yaklaşık 300 hane görebiliyorsunuz, ki bu da sadece 15-20 anlamlı basamaktan oluşan bir ikili mağaza. – flownt

cevap

8

genel fikri ilk uzun 1 ile ve son olarak uzun geri o longBitsToDouble aracılığıyla temsil çift yeni dönüştürmek, artım (eğer getRealBinary yaptıkları gibi doubleToLongBits kullanarak) uzun gösterimine çift dönüştürmek edilir.

DÜZENLEME: Java (1.5'ten beri), Math.ulp(double) sağlar; bu nedenle, bir sonraki daha yüksek değeri doğrudan hesaplamak için kullanabileceğinizi tahmin ediyorum: x + Math.ulp(x).

+2

Java 1.6'dan bu yana, ['Math.nextAfter (başlangıç, yön) '] vardır (http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#nextAfter (double, % 20double)), çok daha güvenilirdir. Sıfır civarında özel durumlarda bile işler. – z0r

7

Kayan nokta numaraları sayı hattı üzerinden eşit yayılmış değildir. Sonsuzluğa yaklaştıkça, 0'a yakın ve çok uzaklarda daha yoğun bir şekilde paketlenirler. Bu nedenle, bir sonraki kayan nokta sayısına ulaşmak için kayan nokta sayısına ekleyebileceğiniz sabit bir sabit yoktur.

+0

Bu nasıl olabilir? Bir mantis ve üs var. Ve ne 0. lehine –

+0

@TonyEnnis: Üs sadece budur - bir üs. Biraz basitleştirilmiş, kayan noktalı bir sayının değeri 'mantissa * 2^üssü' gibi bir şeydir. Yani, mantis değiştirmenin ortaya çıkan sayıyı değiştirdiği miktar, tamamen üssün değerine bağlıdır. Üs kat daha düşük, değişim ne kadar küçük olur. – cHao

4

Sizin kodunuz iyi biçimlendirilmemiş. Minimum çift değeri eklemeye çalışın ve sonucun orijinal değerden farklı olmasını bekliyorsunuz. Sorun şu ki double.MinValue çok küçük ve sonuç yuvarlanıyor ve etkilenmiyor.

de Önerilen okuma: Vikipedi makalesinde Açık http://en.wikipedia.org/wiki/Machine_epsilon

çok Java kodu vardır. Epsilon (= X! X + eps * X) gibi tanım gereği en küçük sayı olduğu ve eps * X "göreli-epsilon" durumunda

0

Eğer BigDecimal sınıfını kullanmak istediğiniz denir, BigDecimal.ulp() yöntemi yoktur de.

1

Java 1.8'den beri tam olarak ne istediğinizi yapmak java.lang.Math.nextUp(double) var. Ayrıca java.lang.Math.nextDown(double)'un tersi de var.

İlgili konular