programing

이중 정밀도 - 소수점 이하

newsource 2022. 8. 12. 23:28

이중 정밀도 - 소수점 이하

제가 읽은 바로는 data type double 값은 대략 소수점 이하 15자리입니다.그러나 1.0/7.0과 같이 소수점 표현이 반복되는 숫자를 사용하면 변수 값이 0.14285714285714285 - 17자리인 것을 알 수 있습니다(디버거를 통해).

왜 내부적으로 17개소로 표기되어 있는지, 왜 15개 정밀도는 항상 ~15개로 표기되어 있는지 알고 싶습니다.

IEEE 더블에는 53개의 유효비트가 있습니다(그 값은DBL_MANT_DIG<cfloat>약 15.95 자리수의 10 진수(log1053(2))입니다.실장 세트는DBL_DIG16이 아니라 15로 줄여서 반올림해야 하니까즉, 거의 십진수 이상의 정밀도를 얻을 수 있습니다.DBL_DIG==15그 때문에).

nextafter()함수는 주어진 숫자에 가장 가까운 대표 가능한 숫자를 계산합니다. 주어진 숫자의 정밀도를 보여주는 데 사용할 수 있습니다.

이 프로그램:

#include <cstdio>
#include <cfloat>
#include <cmath>

int main() {
    double x = 1.0/7.0;
    printf("FLT_RADIX = %d\n", FLT_RADIX);
    printf("DBL_DIG = %d\n", DBL_DIG);
    printf("DBL_MANT_DIG = %d\n", DBL_MANT_DIG);
    printf("%.17g\n%.17g\n%.17g\n", nextafter(x, 0.0), x, nextafter(x, 1.0));
}

시스템 상에서 다음과 같은 출력이 표시됩니다.

FLT_RADIX = 2
DBL_DIG = 15
DBL_MANT_DIG = 53
0.14285714285714282
0.14285714285714285
0.14285714285714288

(교환 가능)%.17g말하자면%.64g더 많은 숫자를 표시하지만, 그 중 어느 것도 마찬가지입니다.

보시는 바와 같이 마지막으로 표시된 10진수는 연속된 각 값에 따라 3씩 변경됩니다.마지막으로 표시된 숫자가1.0/7.0(5이 수학적 값과 일치하는 것은 우연의 일치입니다.그것은 행운의 추측이었습니다.그리고 정확한 반올림 자릿수는6,것은 아니다.5·교환1.0/7.0타고1.0/3.0는 다음 출력을 나타냅니다.

FLT_RADIX = 2
DBL_DIG = 15
DBL_MANT_DIG = 53
0.33333333333333326
0.33333333333333331
0.33333333333333337

16자리 정도의 정밀도를 보여줍니다. 예상대로요.

실제로는 53자리입니다.이것은 안정된 소수점 15자리를 의미합니다.즉, 소수점 15자리를 가진 숫자로 시작 부분을 반올림하면, 그것을 1자리로 변환합니다.double, 그 후,double소수점 이하 15자리까지 같은 숫자를 얻을 수 있습니다.일의로 나타내다double소수점 17자리가 필요합니다(소수점 17자리가 있는 모든 숫자에 대해 고유한 가장 가까운 값이 있습니다).double그렇기 때문에 17개의 장소가 표시되어 있습니다만, 17자리 숫자가 모두 다른 것은 아닙니다.double(다른 답변의 예시와 같이) 값을 지정합니다.

부동 소수점 숫자의 소수점 표현이 좀 이상해요.소수점 이하 15자리 숫자가 있는 숫자를 a로 변환하면double소수점 이하 15자리까지 출력하면 같은 숫자를 얻을 수 있습니다.한편, 만약 당신이 임의의 것을 출력한다면double하면 15자리로 환산됩니다.double, 반드시 같은 값을 얻을 필요는 없습니다.소수점 17자리가 필요합니다.그리고 소수점 15자리나 17자리도 임의의 소수점에 해당하는 정확한 소수점을 정확하게 표시하기에 충분하지 않습니다.double일반적으로 소수점 이하 100자리가 넘어야 정확하게 할 수 있습니다.

이중 정밀도는 위키피디아 페이지를 참조하고 부동 소수점 정밀도에 대한 이 문서를 참조하십시오.

2진수는 53자리, 즉 소수점 이하 15.9545898자리까지 정확하게 유지됩니다.디버거는 이진수 값에 대해 더 정확한 숫자를 원하는 만큼 표시할 수 있습니다.또는 0.1이 기본 10에서 한 자리를 차지하지만 기본 2에서는 무한과 같이 더 적은 숫자와 이진수가 필요할 수 있습니다.

이상하니까 극단적인 예를 보여드릴게요.정확도가 3자리이고 가수나 부호가 없는 초단순 부동 소수점 값을 만드는 경우(따라서 범위는 0-0.875) 옵션은 다음과 같습니다.

binary - decimal
000    - 0.000
001    - 0.125
010    - 0.250
011    - 0.375
100    - 0.500
101    - 0.625
110    - 0.750
111    - 0.875

그러나 숫자를 사용하면 이 형식은 0.903089987 소수점까지만 정확합니다.한 자리도 정확하지 않다. 수 있듯이, 이 없기 에 음음 as as as as as as as as as as as as as as as0.4??도 아니다0.9??그러나 완전한 정확도를 표시하려면 10진수 3자리가 필요합니다.

tl;dr: 디버거는 부동소수점 변수의 값을 임의의 정밀도(사용자의 경우 19자리)로 표시합니다.이것은 부동소수점 형식의 정확도(사용자의 경우 17자리)와 반드시 상관할 필요는 없습니다.

IEEE 754 부동소수는 바이너리로 처리됩니다.주어진 비트수에서 주어진 소수점수로 정확하게 변환되는 것은 없습니다.3비트는 0 ~7의 값을 유지할 수 있으며 4비트는 0 ~15의 값을 유지할 수 있습니다.0 ~ 9 의 값은 약 3.5 비트가 소요되지만, 그것도 정확하지 않습니다.

IEEE 754 배 정밀도는 64비트를 차지합니다.이 중 52비트는 유의(나머지는 부호 비트와 지수) 전용입니다.유의와 (통상) 정규화 되어 있기 때문에 묵시적인rd 53비트가 있습니다.

53비트와 약 3.5비트를 1자리 수로 나누면 15.1429자리의 정밀도를 얻을 수 있습니다.그러나 소수점 당 3.5비트는 근사치일 뿐 완전히 정확한 답은 아닙니다.

많은 디버거들이 실제로 전체 레지스터의 내용을 봅니다.x86에서는 실제로는 80비트 숫자입니다.x86 부동소수점 유닛은 보통 64비트 정밀도로 계산을 수행하도록 조정됩니다.그러나 내부적으로는 몇 개의 "가드 비트"를 사용합니다.이는 기본적으로 내부적으로는 마지막 비트를 올바르게 반올림할 수 있도록 몇 개의 추가 정밀도로 계산을 수행함을 의미합니다.디버거가 전체 레지스터를 볼 때, 보통 상당히 정확한 숫자를 하나 이상 찾습니다. 단, 이 숫자에는 가드 비트가 없기 때문에 올바르게 반올림되지 않을 수 있습니다.

2진수 표현에서 변환되고 있기 때문입니다.모든 소수 자릿수를 출력했다고 해서 모든 소수 자릿수를 그 정밀도로 나타낼 수 있는 것은 아닙니다.예를 들어 Python의 경우 다음과 같습니다.

>>> 0.14285714285714285
0.14285714285714285
>>> 0.14285714285714286
0.14285714285714285

마지막 숫자를 어떻게 바꿨는지 보세요. 그래도 같은 숫자를 출력했어요.

대부분의 컨텍스트에서double값이 사용되고 계산에는 일정량의 불확실성이 있습니다.1.333333333333333300과 1.33333333333399 사이의 차이가 계산에 존재하는 불확실성의 양보다 작을 수 있습니다."2/3 + 2/3" 값을 "1.33333333333333333"으로 표시하는 것이 "1.333333333333333319"로 표시하는 것보다 더 의미 있는 경우가 많습니다. 후자의 표시는 실제로 존재하지 않는 정밀도 수준을 의미하기 때문입니다.

그러나 디버거에서는 본질적으로 무의미한 정밀도 비트를 포함하여 변수에 의해 유지되는 값을 고유하게 표시하는 것이 중요합니다.디버거에서 두 변수가 "1.333333333333333333" 값을 유지하는 것으로 표시되는 경우 두 변수 중 하나는 실제로 1.33333333333319를 보유하고 다른 하나는 1.33333333333333294를 보유하고 있는 경우(두 변수가 동일하지만 동일하지 않다는 의미) 매우 혼란스러울 수 있습니다.디버거에 의해 나타나는 추가 정밀도는 수치적으로 정확한 계산 결과를 나타내지 않지만 코드가 변수에 의해 유지되는 값을 해석하는 방법을 나타냅니다.

언급URL : https://stackoverflow.com/questions/9999221/double-precision-decimal-places