Math.floor neden bir double döndürüyor?


104

Resmi Javadoc , bunun "matematiksel bir tam sayıya eşit olan" Math.floor()a döndürdüğünü söylüyordouble , ancak o zaman neden bir döndürmesin int?

Yanıtlar:


80

Aynı Javadoc'a göre:

Bağımsız değişken NaNveya sonsuz veya pozitif sıfır veya negatif sıfır ise, sonuç bağımsız değişkenle aynıdır. Bunu bir int.

En büyük doubledeğer de en büyüğünden daha büyüktür int, bu nedenle a olması gerekir long.


41
int / long döndüren ve özel durumları farklı bir şekilde ele alan Math.Round işlevleriyle tutarsız görünüyor.
zod

1
Javadoc'un "en büyük (pozitif sonsuza en yakın) * kayan noktalı değeri * , bağımsız değişkenden küçük veya ona eşit ve matematiksel bir tam sayıya eşit olduğunu " söylediğine dikkat edin . Kesirli kısmı kesilmiş değerle aynı olmayacak bir x> 2 ^ 53 değeri verildiğinde . Bundan biraz daha küçük olabilir.
Jim Garrison

16

Hassasiyet için. Çift veri türünün 53 bitlik mantisi vardır. Diğer şeylerin yanı sıra, bu, bir çiftin 2 ^ 53'e kadar olan her şeyi hassasiyet kaybı olmadan temsil edebileceği anlamına gelir.

Bu kadar büyük bir sayıyı bir tamsayı olarak saklarsanız, bir taşma elde edersiniz. Tam sayılar yalnızca 32 bit içerir.

Tamsayıyı çift olarak döndürmek burada yapılacak doğru şeydir çünkü bir tamsayıdan çok daha geniş bir yararlı sayı aralığı sunar.


Bu tür değerlerle başa çıkmak elbette uzun sürebilir. Yine de, 2 ^ 63'ten büyük çiftlerle ne yapacağınızı bulmanız gerekir.
Jon Skeet

1
@Jon, doğru, ancak bu bir performans etkisine neden olur (bildiğim hiçbir komut setinde uzuntan ikiye dönüştürme talimatı yok). Math.floor'un ilk etapta> 2 ^ 53 çiftlerle ne yaptığını merak ediyorum. Bazı sonuçlar gösterilemez.
Nils Pipenbrinck

Ama sonra, resmi javadoc'ta da görünen sözde-deyimsel biçim (int) Math.floor (foo) güvensizdir, çünkü sonuç int'e uymayabilir, değil mi? Ve sonra tekrar, Math.floor'u kullanmak güvenli bir formdur, çünkü sonuç uzun bir süreye bile sığmayabilir?
Raibaz

10

Başkaları size nedenini söylediler, bunu yapmak istemeniz durumunda size nasıl doğru bir şekilde yuvarlanacağınızı anlatacağım. Yalnızca pozitif sayılar kullanacaksanız, bu ifadeyi kullanabilirsiniz:

int a=(int) 1.5;

Bununla birlikte, (int) her zaman 0'a yuvarlanır. Dolayısıyla, negatif bir sayı yapmak istiyorsanız:

int a=(int) -1.5; //Equal to -1

Benim durumumda bunu yapmak istemedim. Yuvarlamayı yapmak için aşağıdaki kodu kullandım ve tüm uç durumları iyi idare ediyor gibi görünüyor:

private static long floor(double a)
{
    return (int) Math.floor(a);
}

7
Neden kullanmıyorsun (int) Math.floor(a)? Muhtemelen daha verimli ve daha kısa.
Solomon Ucko

@Solomon Ucko yerine (int) Math.floor(a)basitçe yazabilirsin (int) a, eğer a pozitifse.
Leo Leontev

3

En büyük int veya long değerinden iki kat daha büyük verirseniz, geri dönmesini ne isterdiniz?

(Kuşkusuz en büyük uzunluktan daha büyükse, hassasiyet yine de düşük olacaktır - en yakın teorik tam sayı olmayabilir - ama öyle bile ...)


0

Java'da bir tamsayı ve bir kayan nokta bölümü olduğu gibi, taban yapmanın tamsayı ve kayan noktalı yolları vardır:

double f = Math.floor(x);

veya

int k = (int) x; 

ancak sonlu kesinlik aritmetiği ile floor kullanırken her zaman dikkatli olmanız gerekir: x'in hesaplanması, 1,99999999 gibi bir sonuç verebilir ve bu, her iki form tarafından 2 değil 1'e katlanacaktır. Bazı girdi değerleri için yanlış sonuçlar üretmekten kaçınmak için bu sınırlamayı aşması gereken birçok algoritma vardır.


0

Böylece bu hata ve diğer tamsayı olmayan değerler, bir dizi hesaplamayla doğru şekilde kademelendirilebilir.

Örneğin, Math.floor'a Bir Sayı Değil (NaN) beslerseniz, onu iletir.

Tamsayı döndürdüyse, bu durumu veya hataları geçemez ve daha önceki bir hesaplamadan iyi görünen ancak daha fazla işlemden sonra yanlış olan kötü sonuçlar alabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.