2016-09-05 5 views
-2

Я запускаю простую программу для проверки пределов вычислений float и integer в C++. Я понимаю, что # 15 и # 19 являются неправильными значениями, которые возвращаются, но почему № 15 конкретно неправильно? И я не думаю, что # 19 делится на 0, чтобы вернуть «inf», так зачем это делать?Неверные возвращаемые значения: C++

#include "stdafx.h" 
#include "stdlib.h" 
#include <iostream> 
#include <math.h> 

float hyp(float x, float y) { 
    return sqrtf(x*x + y*y); 
} 

#include <stdio.h> 
int main(void) { 
    float x = 3.0f, y = 4.0f, z = 5.0f; 
    for (int i = 0; i < 20; i++) { 
     float e = fabsf(hyp(x, y) - z)/z; 
     printf("%2d %e\n", i, e); 
     x *= 10.0f, y *= 10.0f, z *= 10.0f; 
     std::cout << z << std::endl; 
    } 
} 

Результат выглядит следующим образом:

0 0.000000e+00 
50 
1 0.000000e+00 
500 
2 0.000000e+00 
5000 
3 0.000000e+00 
50000 
4 0.000000e+00 
500000 
5 0.000000e+00 
5e+06 
6 0.000000e+00 
5e+07 
7 0.000000e+00 
5e+08 
8 0.000000e+00 
5e+09 
9 0.000000e+00 
5e+10 
10 0.000000e+00 
5e+11 
11 0.000000e+00 
5e+12 
12 0.000000e+00 
5e+13 
13 0.000000e+00 
5e+14 
14 0.000000e+00 
5e+15 
15 1.073742e-07 
5e+16 
16 0.000000e+00 
5e+17 
17 0.000000e+00 
5e+18 
18 0.000000e+00 
5e+19 
19 inf 
5e+20 
Press any key to continue . . . 
+0

Результаты, которые вы видите, зависят от реализации 'sqrtf'. Трудно сказать что-либо помимо этого. Значения x, y и z должны храниться с полной точностью в виде числа десятичных цифр, которые могут быть сохранены без ошибок округления (значение DECIMAL_DIG) в поплавке - '21' (на моей машине не менее). – madmann91

+0

Часть вашего замешательства исходит из предположения, что деление ненулевого числа на ноль - единственный способ получить inf. inf является результатом любой операции, результат которой не может быть представлен конечным числом за слишком большое значение. –

+0

@ madmann91 'DECIMAL_DIG' относится к типу' long double'. Все типы с плавающей запятой здесь 'float'. Реализация C++ может использовать точность «long double» для промежуточных результатов и констант «float», но стандарты C и C++ подразумевают в другом месте, что содержимое переменной «float» должно быть значением, представляемым как 'float'. –

ответ

4

Крупнейшее одинарной точности с плавающей запятой примерно 1.7e+38 (см Wikipedia). Когда вы пытаетесь сделать квадрат 5e+19, результат 2.5e39, который слишком велик, так что вы получите inf.

Причина, по которой вы получаете ненулевой результат для # 15, состоит в том, что с плавающей точкой является приблизительной. См. Is floating point math broken?

Смежные вопросы