2013-06-25 6 views
0

Я пытаюсь создать гистограмму с использованием GSL. У меня возникает проблема, когда я пытаюсь добавить к гистограмме значение деления 1470/100. Это результат 14.69999999, и при добавлении к гистограмме он округляется до нижнего бункера. Мой вопрос: как я могу сделать результат 1470/100 в 14.7, а не 14.69999? СпасибоВопрос об округлении C++

Edit:

int minRange = 14; 
double val; 


val = minRange + j*0.05; 


gsl_histogram_increment(hist, val); 

Когда вал добавляется в гистограмме это считается 14,65 вместо 14,7. (j в этом случае равно 14).

Я решил проблему, добавив 1e-6 в val. Спасибо за помощь.

+0

http://floating-point-gui.de/ – JBL

+0

Возможно, я ошибаюсь здесь, но если вы хотите, чтобы все точки гистограммы округлились, вы не можете сделать что-то вроде раунда (число * 100) /10.0? Можем ли мы извлечь код? Не знаете, какие типы данных вы используете. –

+1

Только для информации: представление '14.7' в плавающей запятой IEEE 754: [32-битный float] (http://www.binaryconvert.com/result_float.html?decimal=049052046055) и [64-битный двойной] (http : //www.binaryconvert.com/result_double.html? decimal = 049052046055) –

ответ

3

Это проблема точности с плавающей точкой. Хорошим способом решения является установка точек гистограммы сразу же за пределы интегральных значений, например. 15 - e, где e имеет порядок 10-6.

0

Да,

Добавление 1e-6 обычно работает, но в целом вы должны быть более осторожными, когда усечения поплавок.

This blog объясните все проблемы, с которыми вы можете столкнуться, если вы хотите объединить числа с плавающей точкой (а также подводные камни наивных решений). Кроме того, предлагают следующую более устойчивую реализацию "добавив, 1Е-6"

float myround(float f) 
{ 
     if (f >= 0x1.0p23) return f; 
     return (float) (unsigned int) (f + 0.49999997f); 
} 

Вы можете проверить, что myround (0.49999997) = 0 и myround (0.49999999) = 1.

Так что я бы прочитал этот блог первым, прежде чем называть этот вопрос полностью решенным!

Еще один момент в том, что C++ 11 имеет новую функцию std :: round, которая возвращает ближайшее целое число, так что вы также можете реализовать округление, сравнивая std::abs(x - std::round(x)) < epsilon, где epsilon - ваша цель. Опять же, это наивная реализация, которая не настолько устойчива, как мой круг (который вам нужно адаптировать к двойному).