C의 부동 소수점 데이터 유형 범위는?
저는 C 책을 읽고 부동소수점의 범위에 대해 이야기하고 있습니다. 저자는 테이블을 주었습니다.
Type Smallest Positive Value Largest value Precision
==== ======================= ============= =========
float 1.17549 x 10^-38 3.40282 x 10^38 6 digits
double 2.22507 x 10^-308 1.79769 x 10^308 15 digits
가장 작은 양의 값과 가장 큰 값 열의 숫자가 어디에서 온 것인지 알 수 없습니다.
32비트 부동 소수점 숫자는 23 + 1비트의 가수를 가지며 8비트 지수(-126 ~ 127)를 사용하므로 표시할 수 있는 가장 큰 숫자는 다음과 같습니다.
(1 + 1 / 2 + ... 1 / (2 ^ 23)) * (2 ^ 127) =
(2 ^ 23 + 2 ^ 23 + .... 1) * (2 ^ (127 - 23)) =
(2 ^ 24 - 1) * (2 ^ 104) ~= 3.4e38
이러한 숫자는 부동 소수점 숫자의 표준 표현을 정의하는 IEEE-754 표준에서 가져온 것입니다.링크의 위키피디아 기사는 부호, 가수 및 지수에 사용되는 비트 수를 알고 이러한 범위에 도달하는 방법을 설명합니다.
float 데이터 유형의 값은 다음과 같이 할당된 숫자를 나타내기 위해 총 32비트를 갖는 것에서 유래합니다.
1비트: 부호 비트
8비트: 지수 p
23비트: 맨티사
지수는 다음과 같이 저장됩니다.p + BIAS
BIAS가 127인 경우, 가수는 23비트와 1로 가정되는 24번째 숨겨진 비트를 가집니다.이 숨겨진 비트는 가수 중 가장 중요한 비트(MSB)이며 지수가 1이 되도록 선택해야 합니다.
이것은 당신이 나타낼 수 있는 가장 작은 숫자는01000000000000000000000000000000
어느 것이1x2^-126 = 1.17549435E-38
.
가장 큰 값은011111111111111111111111111111111
가수는 2 * (1 - 1/65536)이고 지수는 127입니다.(1 - 1 / 65536) * 2 ^ 128 = 3.40277175E38
.
비트가 다음과 같은 경우를 제외하고는 동일한 원리가 이중 정밀도에 적용됩니다.
1비트: 부호 비트
11비트: 지수 비트
52비트: 가수 비트
바이어스: 1023
따라서 기술적으로 한계는 부동 소수점 번호를 표현하기 위한 IEEE-754 표준에서 나온 것이며, 위의 내용은 한계가 발생하는 방식입니다.
무한대, NaN 및 하위 정규 분포
지금까지 다른 답변이 언급하지 않은 중요한 주의 사항입니다.
IEEE 754 및 정상 이하의 숫자에 대한 이 소개를 먼저 읽으십시오.비정규 부동 소수점 수는 무엇입니까?
단일 정밀 부동 소수점(32비트)의 경우:
IEEE 754는 지수가 모두 1이면 다음과 같이 말합니다.
0xFF == 255
), 그런 다음 NaN 또는 Infinity를 나타냅니다.이것이 무한하지 않은 가장 큰 숫자가 지수를 갖는 이유입니다.
0xFE == 254
그리고 아닌0xFF
.그 다음 편향을 사용하면 다음과 같습니다.
254 - 127 == 127
FLT_MIN
는 가장 작은 정규 숫자입니다.하지만 더 작은 정상 이하의 것들도 있습니다!그것들이 차지합니다.-127
지수 슬롯
다음 프로그램의 모든 assert는 Ubuntu 18.04 및 64에 전달됩니다.
#include <assert.h>
#include <float.h>
#include <inttypes.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
float float_from_bytes(
uint32_t sign,
uint32_t exponent,
uint32_t fraction
) {
uint32_t bytes;
bytes = 0;
bytes |= sign;
bytes <<= 8;
bytes |= exponent;
bytes <<= 23;
bytes |= fraction;
return *(float*)&bytes;
}
int main(void) {
/* All 1 exponent and non-0 fraction means NaN.
* There are of course many possible representations,
* and some have special semantics such as signalling vs not.
*/
assert(isnan(float_from_bytes(0, 0xFF, 1)));
assert(isnan(NAN));
printf("nan = %e\n", NAN);
/* All 1 exponent and 0 fraction means infinity. */
assert(INFINITY == float_from_bytes(0, 0xFF, 0));
assert(isinf(INFINITY));
printf("infinity = %e\n", INFINITY);
/* ANSI C defines FLT_MAX as the largest non-infinite number. */
assert(FLT_MAX == 0x1.FFFFFEp127f);
/* Not 0xFF because that is infinite. */
assert(FLT_MAX == float_from_bytes(0, 0xFE, 0x7FFFFF));
assert(!isinf(FLT_MAX));
assert(FLT_MAX < INFINITY);
printf("largest non infinite = %e\n", FLT_MAX);
/* ANSI C defines FLT_MIN as the smallest non-subnormal number. */
assert(FLT_MIN == 0x1.0p-126f);
assert(FLT_MIN == float_from_bytes(0, 1, 0));
assert(isnormal(FLT_MIN));
printf("smallest normal = %e\n", FLT_MIN);
/* The smallest non-zero subnormal number. */
float smallest_subnormal = float_from_bytes(0, 0, 1);
assert(smallest_subnormal == 0x0.000002p-126f);
assert(0.0f < smallest_subnormal);
assert(!isnormal(smallest_subnormal));
printf("smallest subnormal = %e\n", smallest_subnormal);
return EXIT_SUCCESS;
}
GitHub 업스트림.
컴파일 및 실행 방법:
gcc -ggdb3 -O0 -std=c11 -Wall -Wextra -Wpedantic -Werror -o subnormal.out subnormal.c
./subnormal.out
출력:
nan = nan
infinity = inf
largest non infinite = 3.402823e+38
smallest normal = 1.175494e-38
smallest subnormal = 1.401298e-45
dasblinkenlight가 이미 답했듯이, 그 숫자들은 IEEE-754에서 부동소수점 숫자가 표현되는 방식에서 나온 것이고, Andreas는 수학에 대한 멋진 분석을 가지고 있습니다.
그러나 IEEE-754 숫자의 정밀도는 유의한 이진 숫자의 수에 따라 달라지므로 부동 소수점 숫자의 정밀도가 표에서 제시하는 것처럼 정확하게 6자리 또는 15자리 유의한 소수점 숫자가 아닙니다.
float
에는 24개의 유효한 이진 숫자가 있습니다. 이 숫자는 표시된 숫자에 따라 6-8개의 소수 자릿수 정밀도로 변환됩니다.double
에는 53개의 유효한 이진 숫자가 있으며, 이는 약 15개의 소수 자릿수입니다.
관심이 있으시다면 제 다른 답변에 더 자세한 설명이 있습니다.
예를 들어 IEEE 754와 같이 유형의 지수 부분의 크기에 따른 결과입니다.float.h의 FLT_MAX, FLT_MIN, DBL_MAX, DBL_MIN으로 크기를 검사할 수 있습니다.
언급URL : https://stackoverflow.com/questions/10108053/ranges-of-floating-point-datatype-in-c
'programing' 카테고리의 다른 글
Mysql/Mariadb 사용자가 여러 데이터베이스에 부여 (0) | 2023.07.22 |
---|---|
장고 프로젝트에서 from django.conf 가져오기 설정과 가져오기 설정의 차이점은 무엇입니까? (0) | 2023.07.22 |
한 열에서 고유한 열을 선택하고 다른 모든 열을 반환합니다. (0) | 2023.07.22 |
함수 arg에 액세스하기 위해 x86 스택을 popping할 때의 세그먼트화 오류 (0) | 2023.07.22 |
SpringBoot - HTTP 요청 헤더 구문 분석 오류 (0) | 2023.07.22 |