2016-08-22 27 views
6

Czy istnieje różnica precyzji pomiędzy poniższymi (zakładając, że wartość aib może być reprezentowana bez utraty precyzji w float).Float vs double Math Java

Z pływaków:

float a; 
float b; 
double result = 1 + a*b; 

W deblu:

double a; 
double b; 
double result = 1 + a*b; 
+0

Istnieje z definicji; 'float' to 32-bitowy, podstawowy 2 IEEE 754 zmiennoprzecinkowy, podczas gdy' double' jest 64-bitowy. Jedynym zdarzeniem, w którym nie jest to prawdą, jest to, że wszystkie trzy wejścia i wyniki mogą się zmieścić w 'float'. – fge

+0

Zasadniczo chciałem się dowiedzieć, czy Java konwertuje a * b do debla za kulisami. Z odpowiedzi widzę, że tak nie jest. – Quirion

Odpowiedz

6

Prosty przykład:

float a = 16777217; // Largest int exactly representable in a float. 
float b = 16777217; 
System.out.println((double)(1 + a*b)); 

double c = 16777217; 
double d = 16777217; 
System.out.println(1 + c*d); 

wyjściowa (Ideone):

2.81474976710656E14 
2.8147501026509E14 

Więc tak, jest utrata dokładności przy użyciu float.

+0

Aby uzupełnić odpowiedź, możesz dodać uwagę, o której wspomniał Peter Lawrey, że a * b jest zmiennoprzecinkową, gdy aib są unoszone. – Quirion

0

Nie może być utrata różnicy precyzji w ramach * B podczas oceniania go jako pływaków i podwaja. Tak, z pewnymi wartościami, druga będzie bardziej dokładna.

3

Jest utrata precyzji w

float a; 
float b; 
double result = 1 + a*b; 
  • reprezentacji float.
  • produkt z a i b, który również będzie oznaczony jako float. Uwaga: a * b jest dodatkiem na 1 może spowodować utratę precyzji.

Aby powinny że a * b może stracić większą precyzją

for (int i = 1; i < 100; i += 2) { 
    float a = i; 
    float b = 1.0f/i; 
    if ((double) a * b != a * b && a * b != 1) 
     System.out.println(i + " " + (double) a * b + " " + a * b); 
} 

wydruki

41 0.999999962747097 0.99999994 
47 0.9999999683350325 0.99999994 
55 0.9999999683350325 0.99999994 
61 0.9999999441206455 0.99999994 
83 0.999999962747097 0.99999994 
97 0.999999969266355 0.99999994 

uwaga: może to również zdarzyć odzyskać precyzję utracone i uzyskać właściwą odpowiedź po b traci precyzję

for (int i = 1; i < 20; i += 2) { 
    float a = i; 
    float b = 1.0f/i; 
    if (b != 1.0/i && a * b == 1) 
     System.out.println(i + " " + (double) a * b + " " + a * b); 
} 

drukuje

3 1.0000000298023224 1.0 
5 1.0000000149011612 1.0 
7 1.0000000447034836 1.0 
9 1.0000000074505806 1.0 
11 1.0000000298023224 1.0 
13 1.000000037252903 1.0 
15 1.0000000521540642 1.0 
17 1.0000000037252903 1.0 
19 1.0000000074505806 1.0 
+0

Czy "float b = -1,0f/i" reprezentuje się bez utraty precyzji? – Quirion

+0

@Quirion tylko, jeśli 'i' jest potęgą 2. W przeciwnym razie występuje utrata precyzji, która może się pogorszyć lub zniknąć po pomnożeniu przez' i' –

+0

Więc twoja odpowiedź nie jest aktualna, ponieważ tracisz precyzję w momencie przypisania float b = -1,0 f/i; , ale pytanie stwierdziło, że aib mogą być przedstawiane bez utraty precyzji. Interesowało mnie zrozumienie, czy mnożenie spowodowało utratę precyzji, i robi to, ponieważ a * b jest traktowane jako float, jak wspomniałeś. – Quirion