2013-08-11 9 views
7

Mam ten kodGetting nieoczekiwane wyniki, gdy typ odlewania między długim i podwójnym

public class LimitTest{ 
    public static void main(String[] args){ 
     long l; 
     double d; 
     l = 9223372036854775807L;// The largest number a long can hold. 
     d = l; 
     System.out.println(l); 
     System.out.println(d); 
     System.out.println(l == d); 
    } 
} 

Teraz wynikiem produkuje jest dosyć nieoczekiwany, ale znowu, nie jestem bardzo doświadczony z typu konwersji.

Wyjście

9223372036854775807 
9.223372036854776E18 
true 

Teraz, dwa numery drukowane są wyraźnie NIE RÓWNE, więc dlaczego l == d powrotną true?

Odpowiedz

5

Zmienne l i d mają różne typy, więc wyrażenie long == double rzuca long do double ...

PS: l to zła nazwa zmiennej imho, ponieważ wygląda bardzo podobnie do 1 podczas przeglądania kodu.

2

więc dlaczego l == d return true ;

Ponieważ long jest konwertowane na double przed porównaniem. I stąd wynik jest prawdziwy.

to określono w JLS - Section 5.6.2:

Rozszerzenie prymitywny konwersji (§5.1.2) nakłada się konwersję jednego lub obu argumentów jak określono według następujących zasad:

  • Jeżeli jedna operand typu double, druga jest konwertowana na podwójną.

Widzisz inny wynik dla double, ponieważ nie wszystkie wartości long może być reprezentowany przez unikalną wartość double. Być może masz wiele podwójnych wartości dla pojedynczej długiej wartości. Istnieje możliwość utraty dokładności podczas konwersji z long na double.

Od JLS Section 5.1.2:

poszerzenie konwersja int lub długiej wartości do float, lub długiego wartości podwoić, może spowodować utratę precyzji - to znaczy, że wynik może stracić niektóre z najmniej znaczących bitów wartości.

2

Aby porównać dwie wartości, muszą one być tego samego typu. W tym przypadku wartość długa jest niejawnie przekształcana w typ podwójny, a wynik konwersji daje tę samą wartość, co przypisanie.

Wartości są różne przede wszystkim dlatego, że podwójny typ ma mniej "znaczenia" (ma 53-bitową mantysę do przechowywania rzeczywistych cyfr, pozostałe bity są używane dla znaku i wykładnika) niż długo (wszystkie 64 bity). Nie wszystkie długie wartości mogą być reprezentowane jako unikalna podwójna wartość.

2

9223372036854775807 i 9.223372036854776E18są równe

Uwaga pierwsze 15 cyfr precyzji 922337203685477 są takie same. Reszta pierwszego numeru 5807 zostaje zaokrąglona do 6, dzięki czemu można dołączyć E18.

9223372036854775807 w notacji naukowej:

9.223372036854775807 x 10^18 == 9.223372036854775807E18 

Porównaj:

9.223372036854775807E18 
9.223372036854776E18 

Wartość ta jest przechowywana z większą precyzją niż jest wyświetlana z, zobaczyć to na dowód:

long l; 
    double d; 
    l = Long.MAX_VALUE;// The largest number a long can hold. 
    d = l; //This is implicitly cast to (double) 
    System.out.println("long: " + l); 
    System.out.println("double: " + d); 
    System.out.println("double back to long: " + (long) d); 

długa: 9223372036854775807
podwójnie: 9.223372036854776E18
podwójnego back długo: 9223372036854775807

Istnieje również kwestią drugorzędną, jak pływaki oraz dwuosobowe są przechowywane. Podczas gdy typy całkowite (bajt, krótki, int, long) są dokładnie, zmiennoprzecinkowymi i podwójnie stosowanymi stylami wykładniczo-wykładniczymi IEEE754, co pozwala im reprezentować większy zakres liczb, ale z mniejszą dokładnością. http://en.wikipedia.org/wiki/IEEE_754-1985

Powiązane problemy