program tip

0.1 float는 0.1 double보다 큽니다.

radiobox 2020. 8. 20. 08:09
반응형

0.1 float는 0.1 double보다 큽니다. 나는 그것이 거짓 일 것으로 예상했다 [중복]


허락하다:

double d = 0.1;
float f = 0.1;

표현해야

(f > d)

반환 true또는 false?

경험적으로 대답은 true입니다. 그러나 나는 그것이 false.

로이 0.1두 번있는 동안 완벽하게, 이진수로 표현할 수없는 1516정밀의 진수, 및 플로트는있다 7. 따라서 둘 다보다 작으며 0.1이중이 더 가깝습니다 0.1.

에 대한 정확한 설명이 필요합니다 true.


나는를 변환 할 때 대답은 반올림 모드에 따라 달라집니다 말하고 싶지만 double으로 float. float24 개의 이진 비트 정밀도를 double가지며 53을 갖습니다. 이진법에서 0.1은 다음과 같습니다.

0.1₁₀ = 0.0001100110011001100110011001100110011001100110011…₂
             ^        ^         ^   ^ 
             1       10        20  24

우리는 반올림이 경우 최대 24 자리에서, 우리는거야

0.1₁₀ ~ 0.000110011001100110011001101

이는 정확한 값보다 크고 53 자리에서 더 정확한 근사값입니다.


숫자 0.1은 주어진 정밀도로 가장 가까운 부동 소수점 표현으로 반올림됩니다. 이 근사는 0.1보다 크거나 작을 수 있으므로 실제 값을 보지 않고는 단 정밀도 또는 배정 밀도 근사가 더 큰지 예측할 수 없습니다.

다음은 배정 밀도 값이 반올림되는 값입니다 (Python 인터프리터 사용).

>>> "%.55f" % 0.1
'0.1000000000000000055511151231257827021181583404541015625'

다음은 단 정밀도 값입니다.

>>> "%.55f" % numpy.float32("0.1")
'0.1000000014901161193847656250000000000000000000000000000'

따라서 단 정밀도 근사가 더 크다는 것을 알 수 있습니다.


.1바이너리 로 변환하면 다음 을 얻을 수 있습니다.

0.000110011001100110011001100110011001100110011001100 ...

영원히 반복

데이터 유형에 매핑하면 다음을 얻을 수 있습니다.

float (.1) = % .00011001100110011001101
                                     ^ --- 반올림 참고
double (.1) = % .0001100110011001100110011001100110011001100110011010

10 진수로 변환 :

float (.1) = .10000002384185791015625
double (.1) = .100000000000000088817841970012523233890533447265625

이것은 Bruce Dawson이 쓴 기사에서 가져온 것입니다. 여기에서 찾을 수 있습니다.
복식은 수레가 아니므로 비교하지 마십시오.


질문에 대한 Eric Lippert의 의견 이 실제로 가장 명확한 설명 이라고 생각 하므로 답변으로 다시 게시하겠습니다.

3 자리 십진수와 6 자리 십진수로 1/9를 계산한다고 가정합니다. 0.111 <0.111111, 맞죠?

이제 6/9를 계산한다고 가정합니다. 0.667> 0.666667, 맞죠?

6/9에 가장 가까운 3 자리 10 진수가 아니기 때문에 3 자리 십진수의 6/9가 0.666이라는 것을 가질 수 없습니다!


정확히 표현할 수 없기 때문에 2 진법에서 1/10을 비교하는 것은 10 진법에서 1/7을 비교하는 것과 같습니다.

1/7 = 0.142857142857 ...하지만 다른 기본 10 정밀도 (소수점 3 대 6 자리)에서 비교하면 0.143> 0.142857이됩니다.


Just to add to the other answers talking about IEEE-754 and x86: the issue is even more complicated than they make it seem. There is not "one" representation of 0.1 in IEEE-754 - there are two. Either rounding the last digit down or up would be valid. This difference can and does actually occur, because x86 does not use 64-bits for its internal floating-point computations; it actually uses 80-bits! This is called double extended-precision.

So, even among just x86 compilers, it sometimes happen that the same number is represented two different ways, because some computes its binary representation with 64-bits, while others use 80.


In fact, it can happen even with the same compiler, even on the same machine!

#include <iostream>
#include <cmath>

void foo(double x, double y)
{
  if (std::cos(x) != std::cos(y)) {
    std::cout << "Huh?!?\n";  //← you might end up here when x == y!!
  }
}

int main()
{
  foo(1.0, 1.0);
  return 0;
}

See Why is cos(x) != cos(y) even though x == y? for more info.


The rank of double is greater than that of float in conversions. By doing a logical comparison, f is cast to double and maybe the implementation you are using is giving inconsistent results. If you suffix f so the compiler registers it as a float, then you get 0.00 which is false in double type. Unsuffixed floating types are double.

#include <stdio.h>
#include <float.h>

int main()
{
     double d = 0.1;
     float f = 0.1f;
     printf("%f\n", (f > d));

     return 0;
}

참고URL : https://stackoverflow.com/questions/19292283/0-1-float-is-greater-than-0-1-double-i-expected-it-to-be-false

반응형