2016-09-08 3 views
-1

Я хочу округлить значение поплавка, скажем val до ближайшего кратного 0.05. Объяснение моего намерения - here. У меня уже есть верхняя и нижняя границы val, скажем valU и valL соответственно. Я могу сделать это следующими способами:Округление поплавка до двух знаков после запятой

  1. Поиск ближайшего кратного 0,05 в диапазоне [valL, valU] и присваивание значения соответственно. Зависимость зависит от более низкой стоимости. ИЛИ
  2. Использование чего-то вроде this (замена взамен 20 на 100 в решении, указанном в ссылке).

Я нахожу, что метод-2 дает неправильные результаты несколько раз. Может кто-нибудь, пожалуйста, скажите мне, почему метод-1 правильный?

+3

Способ 2 лучше всего, покажите свой код. – Barmar

+0

Обязательно опубликуйте соответствующий материал ** здесь **. Связанные данные - это только справочные данные. – chux

ответ

1

... вокруг значения float, скажем val до ближайшего числа, кратного 0,05 ...

Учитывая типичный binary floating point, самое лучшее, что можно было это

... круглый a float значение до ближайшего к краю 0,05 R и сохранять как ближайшее представительство floatr.


Метод № 1 неясен в угловых случаях. Что OP не является кодом, а контуром кода с математической точки зрения, а не с фактическим C-кодом. Я бы пошел с вариацией на # 2, которая работает очень ну. @Barmar

Практически метод 2: Умножьте, округлите, затем разделите.

#include <math.h> 
double factor = 20.0; 
float val = foo(); 
double_or_float rounded_val = round(val * factor)/factor; 

Этот метод имеет две тонкие точки, которые делают его превосходным.

  1. Умножение выполняется с большей точностью и диапазоном, чем ссылочного ответ - это позволяет для точного продукта и точный фактор очень. Если произведение/фактор было рассчитано только с математикой float, некоторые случаи кросс-кода оказались бы неправильным ответом, и, конечно, некоторые большие значения переполнились бы до бесконечности.

  2. «Связи разрешаются путем принятия более низкого значения». это жесткая и необычная цель. Похоже на цель, направленную на перекос. round(double) красиво округляет половину случайности от нуля независимо от текущего направления округления. Чтобы выполнить «нижний», измените текущее направление округления и используйте rint() или nearbyint().

    #include <fenv.h> 
    int current_rounding_direction = fegetround(); 
    fesetround(FE_DOWNWARD); 
    double rounded_val = rint(val * factor)/factor; 
    fesetround(current_rounding_direction); 
    

... метод-2 дает неправильные результаты несколько раз ...

ОП необходимо разместить код и точных значений, используемых и рассчитанные для качественного объяснения сильных/слабых сторон различных методов. Попробуйте printf("%a %a\n", val, rounded_val);. Часто проблемы возникает из-за неточного понимания точных значений, используемых должны закодировать Используйте printf("%f\n", val);


Далее:. «У меня уже есть верхние и нижние границы из val, скажем valU и valL соответственно я могу сделать это в следующем Пути: «

Это сомнительно точное, так как отклонение valU и valL - это просто итерация исходной проблемы - найти rounded_val. Код для поиска valL и valU для каждой из них должен иметь верхнюю и нижнюю границы, иначе что должно помешать диапазону [valL ... valU] от себя с неточными конечными точками?

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