'float'vs. 'double'정밀도


155

코드

float x  = 3.141592653589793238;
double z = 3.141592653589793238;
printf("x=%f\n", x);
printf("z=%f\n", z);
printf("x=%20.18f\n", x);
printf("z=%20.18f\n", z);

당신에게 출력을 줄 것이다

x=3.141593
z=3.141593
x=3.141592741012573242
z=3.141592653589793116

여기서 출력의 세 번째 줄 741012573242은 쓰레기이고 네 번째 줄 116은 쓰레기입니다. 플로트에는 항상 16 개의 유효 숫자가 있고 플로트에는 항상 7 개의 유효 숫자가 있습니까? 왜 복식에는 14 개의 유효 숫자가 없습니까?

답변:


146

C의 부동 소수점 숫자는 IEEE 754 인코딩을 사용합니다.

이 유형의 인코딩은 부호, 의미 및 지수를 사용합니다.

이 인코딩으로 인해 많은 숫자가 저장 될 수 있도록 약간의 변경이 있습니다.

또한 유효 자릿수는 10 진수가 아닌 2 진수 표현이므로 약간 변경 될 수 있습니다.

단 정밀도 (float)는 23 비트의 유효 숫자, 8 비트의 지수 및 1 개의 부호 비트를 제공합니다.

배정도 (double)는 52 비트의 유효 숫자, 11 비트의 지수 및 1 개의 부호 비트를 제공합니다.


4
C99는 이전에는 컴파일러에 달려있었습니다.
Alan Geleynse

21
-1이 진술은 명백히 거짓입니다 : "이 인코딩으로 인해, 당신은 당신의 가치가 변하지 않을 것이라고 보장 할 수 없습니다."
R .. GitHub 중지 도움 얼음

16
@Alan : C99에는 IEEE 부동 소수점이 필요하지 않습니다. 그냥 추천합니다.
R .. GitHub 중지 도움 얼음

4
@Alan : R ..이 맞습니다. 부록 F (IEEE-754 바인딩을 지정)는 표준이지만 구현에서 정의한 경우에만 유효합니다 __STDC_IEC_559__. 해당 매크로를 정의하지 않은 구현은 IEEE-754를 준수하지 않습니다.
Stephen Canon

12
@Alan : 아래에서 IEEE 754, 쉽게 값에 변화가 없음을 보장 할 것 0.5, 0.046875또는 0.376739501953125진수 표현 비교가. (이것은 가수에 분자 피팅이 있고 지수에있는 분모 피팅의 밑이 2 인 로그가있는 모든 이차적 이성론입니다.)
R .. GitHub STOP HELPING ICE

42

플로트에는 항상 16 개의 유효 숫자가 있고 플로트에는 항상 7 개의 유효 숫자가 있습니까?

아니요. Double은 항상 53 개의 유효 비트를 가지며 float는 항상 24 개의 유효 비트를 갖습니다. (비정규, 무한 및 NaN 값은 제외하지만 다른 질문의 대상 임). 이들은 이진 형식이며 이진 숫자 (비트)로 표현의 정확성에 대해서만 명확하게 말할 수 있습니다.

이것은 부호없는 32 비트 정수는 최대 32 비트의 정수를 저장할 수있는 십진수에 정확하게 매핑되지 않는 정수를 저장할 수있는 수의 문제와 유사합니다. 십진수 9 자리를 저장할 수 있지만 10 자리 숫자도 많이 저장할 수 있습니다.

왜 복식에는 14 개의 유효 숫자가 없습니까?

double의 인코딩은 64 비트 (부호의 경우 1 비트, 지수의 경우 11 비트, 52 개의 명시 적 유효 비트 및 1 개의 암시 적 비트)를 사용하는데, 이는 부동 (32 비트)을 나타내는 데 사용되는 비트 수의 두 배 입니다.


15

float : 23 비트의 부호, 8 비트의 지수 및 1 개의 부호 비트.

double : 52 비트의 부호, 11 비트의 지수 및 1 개의 부호 비트.


11

일반적으로 기수 10이 아닌 기수 2와 지수 2의 유의 한 수치를 기반으로합니다. 그러나 C99 표준에서 알 수 있듯이 float 및 double에 대한 지정된 정밀도는 없습니다 (1 및 1 + 1E-5/ 1 + 1E-7구별 [ floatdouble 총 36]). 그러나 유효 숫자의 수는 구현 자에게 맡겨져 있습니다 (내부에서 사용하는베이스뿐만 아니라, 따라서 구현에서는베이스 3의 정밀도 18 자리수를 기반으로 결정할 수 있습니다). [1]

이 값을 알아야 할 경우 상수 FLT_RADIXFLT_MANT_DIG(및 DBL_MANT_DIG/ LDBL_MANT_DIG)는 float.h에 정의됩니다.

그것이 호출되는 이유는 그것을 double저장하는 데 사용 된 바이트 수가 부동 소수점 수의 두 배이기 때문입니다 (그러나 여기에는 지수와 의미가 모두 포함됩니다). IEEE 754 표준 (대부분의 컴파일러에서 사용)은 지수보다 지수에 상대적으로 더 많은 비트를 할당하므로 (23에서 9는 float대 52에서 12로 double) 정밀도가 두 배 이상인 이유입니다.

1 : 섹션 5.2.4.2.2 ( http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf )


오식? C89은 최대의 엡실론 필요 1E-9double하지를 1E-7.
Rufflewind


4

그것은 정확히 아니다 더블 때문에 방법의 정밀도 IEEE 754 이진 정말 소수에 잘 번역하지 않기 때문에 작동합니다. 관심이 있다면 표준을 살펴보십시오.


4

float는 부동 소수점 숫자를 나타냅니다 .C에서 float 데이터 형식은 총 자릿수의 정밀도가 7 인 경우에 사용됩니다. 예를 들면 다음과 같습니다. 12.3546987은 총 9 자리 숫자로 플로트에 저장할 수 없습니다. 출력은 12.354699로 표시됩니다. 즉, 처음 7 자리는 입력에 입력 된 것으로 표시되고 8 자리는 반올림됩니다. 대략 1.5 x 10 ^ (-45)에서 3.4 x 10 ^ (38)까지의 범위 메모리 할당 측면에서 float는 단 정밀도 32 비트 부동 소수점 데이터 유형입니다.

float와 달리 double은 정밀도가 15 ~ 16 자리이며 double의 범위는 5.0 × 10 ^ (− 345) ~ 1.7 × 10 ^ (308)입니다. 바이트 할당 측면에서 double은 64 비트 부동 소수점 데이터입니다. 유형.

float 또는 double은 printf에 영향을 미치지 않지만 scanf의 경우 총 데이터 수에 따라 적절한 데이터 유형이 사용됩니다. 부동 번호의 자릿수 입력에서 읽습니다.

따라서 데이터 정확도를 높이려면 float보다 double이 선호됩니다.

도움이 되었기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.