2017-11-18 25 views
0

부동 소수점 산술, 발생하는 오류 및 누적 발생에 대한 올바른 이해를 얻으려고하고 있으며 결과가 정확히 어떻게 발생 하는지도 알아 내려고합니다. 여기서 특히 3 예 I는 현재 일하고된다특정 부동 소수점 계산이 왜 그런 식입니까? (예 : 123456789f +1 = 123456792)

1)0.1 + 0.1 +0.1 +0.1 +0.1 +0.1 +0.1 +0.1 +0.1 +0.1 -1.0 = -1.1102230246251565E-16 또 다른 0.1 10 번을 추가하면 1.0보다 약간 작은 숫자가 나옵니다. 그러나 0.10.1보다 약간 큰 것으로 표시됩니다 (double 값). 또한 * 0.1 * 3 *이고 약간 큰 0.3하지만 * 0.1 * 8 * 약간 작은 0.8

2)123456789f + 1 = 123,456,792 및 123456789f +4 = 123456800.

그 결과는 무엇입니까? 이 모든 것이 여전히 조금 신비 스럽습니다.

답변

4

일반적인 현대 프로세서 및 프로그래밍 언어는 float에 32 비트 이진 부동 소수점을 사용하고 double에 64 비트 이진 부동 소수점을 사용하여 IEEE-754 산술 (다소간)을 사용합니다. double에는 53 비트 유효 숫자가 사용됩니다. 이는 10 진수가 double으로 변환되면,이 몇개 S• 2 F ES는 표시이다 (+1 또는 -1) •, 으로 변환되어 있음을 의미 f은 53 비트로 표현할 수있는 부호없는 정수이며 e은 -1074와 971 사이의 정수입니다. (또는 변환되는 숫자가 너무 큰 경우 결과는 + 무한 또는 - 무한 일 수 있습니다.) 부동 소수점 형식을 알고있는 사용자는 지수가 -1023에서 1023 사이에 있다고 잘못 말할 수 있지만 소수점 이하 자릿수를 정수로 만드는 것입니다. 인코딩이 아닌 수학적 값을 설명하고 있습니다.) 필요한 형식의 모든 숫자 중 가장 가까운 숫자로, .1에서 double으로 변환하면 3602879701896397/36028797018963968이됩니다. 1. 분모는 2 -55이므로 e은 -55입니다.

두 개를 추가하면 7205759403792794/36028797018963968이됩니다. 분자는 여전히 2 보다 작으므로 형식이 맞습니다.

세 번째 3602879701896397/36028797018963968을 추가하면 수학적 결과는 10808639105689191/36028797018963968입니다. 불행히도 분자는 너무 큽니다. 2 (9007199254740992)보다 큽니다. 따라서 부동 소수점 하드웨어는 해당 숫자를 반환 할 수 없습니다. 그것은 어쨌든 그것을 적합하게해야합니다.

분자와 분모를 2로 나누면 5404319552844595.5/18014398509481984가됩니다.이 값은 같지만 분자는 정수가 아닙니다. 하드웨어를 적합하게 만들기 위해 하드웨어는이를 정수로 반올림합니다. 분수가 정확하게 1/2 일 때 규칙은 결과를 균등하게 만들기 위해 반올림하므로 하드웨어는 5404319552844596/18014398509481984를 반환합니다.

다음으로 현재 합계 5404319552844596/18014398509481984를 취하여 3602879701896397/36028797018963968을 다시 추가합니다. 이 시간, 합이 경우 7205759403792794.5/18014398509481984.이며, 하드웨어는 7205759403792794/18014398509481984.

그런 다음 우리가 18,014,398,509,481,984분의 7,205,759,403,792,794 및 36,028,797,018,963,968분의 3,602,879,701,896,397을 추가, 반환, 내림과 합 9007199254740992.5/18014398509481984. 주입니다 그 분자는 분수를 가질뿐만 아니라 2 보다 큽니다. 따라서 우리는 이것을 다시 줄여서 4503599627370496.25/900719925474099를 만들어야합니다. 분자를 정수로 반올림하면 4503599627370496/9007199254740992가 생성됩니다.

정확히 1/2입니다. 이 시점에서 반올림 오류는 우연히 취소되었습니다. .1 5 번을 추가하면 정확히 .5가됩니다. 우리가 9,007199254740,992분의 4,503599627370,496 및 36,028,797,018,963,968분의 3,602,879,701,896,397을 추가 할 때

는, 결과는 하드웨어가 내림 정확히 5404319552844595.25/9007199254740992. 및/9007199254740992.

5404319552844595 지금 우리가 반복적으로 내림하려고 볼 수 있습니다 반환합니다. 누적 합계에 3602879701896397/36028797018963968을 추가하려면 하드웨어가 분자를 4로 나눠서 일치시켜야합니다. 즉, 분수 부분은 항상 .25가 될 것이고, 반올림됩니다. 따라서 다음 4 개의 합계도 반올림됩니다. 우리는, 분자가 24 비트에 맞지하는 단지 적은 대신 doublefloat 함께

1보다 9,007199254740,992분의 9,007199254740,991로 끝낸다 그래서 미만 24 (16777216)이어야한다. 따라서 123456789는 산술 연산이 완료되기 전에 너무 큽니다. 그것이 15,432,099 • 2 3로 표현되어야 123456792. 1을 가산의 정확한 수학적 결과 15432099.125 • 2 3이며, 정수 해당 유효수 라운딩 수율 15,432,099 • 2 3 때문에 존재 변경 없음. 그러나 4를 더하면 15432099.5 • 2 이되고 그 값은0 • 2 으로 반올림됩니다.