Google 계산기 결함은 부동 대 부동(float)이 될 수 있습니다.이중 가능한 이유가 있습니까?
-
09-06-2019 - |
문제
나는 단지 재미삼아 이 작업을 수행했지만(따라서 정확히 질문은 아니지만 이미 다운모딩이 진행되고 있음을 알 수 있습니다) Google의 새로운 발견 대신 할 수 없음 할 것 수학 바르게 (확인해 봐!Google 500,000,000,000,002 - 500,000,000,000,001 = 0)에 따르면, 나는 약간의 이론을 실행하기 위해 C에서 다음을 시도해 볼 것이라고 생각했습니다.
int main()
{
char* a = "399999999999999";
char* b = "399999999999998";
float da = atof(a);
float db = atof(b);
printf("%s - %s = %f\n", a, b, da-db);
a = "500000000000002";
b = "500000000000001";
da = atof(a);
db = atof(b);
printf("%s - %s = %f\n", a, b, da-db);
}
이 프로그램을 실행하면 다음과 같은 결과가 나옵니다.
399999999999999 - 399999999999998 = 0.000000
500000000000002 - 500000000000001 = 0.000000
Google이 단순한 32비트 부동 정밀도(여기서는 오류)를 사용하는 것처럼 보입니다. 위 코드에서 부동 소수점을 double로 전환하면 문제가 해결됩니다!이게 아닐까?
/mp
해결책
C #에서 (double.maxvalue== (double.maxvalue-100)) 시도하면 true가됩니다 ...
하지만 그게 당연한 것입니다 :
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
생각해 보면 2 ^ 64 (double.maxvalue)보다 큰 숫자를 나타내는 64 비트가 있으므로 부정확성이 예상됩니다.
다른 팁
이러한 종류의 어리 석음에 대한 자세한 내용은 Windows 계산기와 관련된이 멋진 기사를 참조하십시오.
Google이 단순한 32 비트 부동 정밀도 (여기서는 오류)를 사용하는 것 같습니다. 위 코드에서 float를 double로 전환하면 문제가 해결됩니다!이것이 가능할까요?
아니요, 문제를 연기하면됩니다.복식은 더 큰 숫자로만 동일한 문제를 나타냅니다.
@ebel
생각해 보면 2^64(double.maxvalue)보다 큰 숫자를 나타내는 64비트가 있으므로 부정확성이 예상됩니다.
2^64는 double의 최대값이 아닙니다.2^64는 double(또는 다른 64비트 유형)이 보유할 수 있는 고유 값의 수입니다. Double.MaxValue
1.79769313486232e308과 같습니다.
부동 소수점 숫자의 부정확성은 다음보다 큰 값을 나타내는 데서 발생하지 않습니다. Double.MaxValue
(이를 제외하면 불가능합니다. Double.PositiveInfinity
).이는 원하는 값 범위가 너무 커서 데이터 유형에 맞지 않는다는 사실에서 비롯됩니다.그래서 우리는 더 큰 유효 범위를 대가로 정밀도를 포기합니다.본질적으로 우리는 더 큰 지수 범위에 대한 대가로 유효 숫자를 삭제하고 있습니다.
@DrPizza
심지어는 아닙니다.IEEE 인코딩은 동일한 값에 대해 여러 인코딩을 사용합니다.특히 NaN은 all-bits-1의 지수와 가수의 0이 아닌 값으로 표현됩니다.따라서 복식에는 252개의 NaN이 있고, 단식에는 223개의 NaN이 있습니다.
진실.중복 인코딩을 고려하지 않았습니다.실제로는 2개가 있다52복식의 경우 -1 NaN 및 223그러나 싱글의 경우 -1 NaN입니다.:피
2 ^ 64는 double의 최대 값이 아닙니다.2 ^ 64는 double (또는 다른 64 비트 유형)이 보유 할 수있는 고유 한 값의 수입니다.Double.MaxValue는 1.79769313486232e308과 같습니다.
고르지 않습니다.IEEE 인코딩은 동일한 값에 대해 여러 인코딩을 사용합니다.특히 NaN은 all-bits-1의 지수와 가수에 대해 0이 아닌 모든 값으로 표시됩니다.따라서 복식의 경우 2 52 NaN, 싱글의 경우 2 23 NaN이 있습니다.
맞습니다.중복 인코딩을 고려하지 않았습니다.실제로 복식의 경우 252-1 NaN이 있고 싱글의 경우 223-1 NaN이 있습니다.: p
도우, 무한도 빼는 걸 잊었 네요.
제가 배운이 문제의 대략적인 추정 버전은 32 비트 부동 소수점은 5 자리 정밀도를 제공하고 64 비트 부동 소수점은 15 자리 정밀도를 제공한다는 것입니다.물론 이것은 float가 인코딩되는 방법에 따라 다르지만 꽤 좋은 시작점입니다.