Как правильно «привязать» к значению? - PullRequest
0 голосов
/ 18 января 2019

Допустим, я установил шаг 0,1 в своем приложении. Итак, какое бы значение fp я ни получал, мне просто нужна 1 цифра после запятой.

Итак, 47.93434 должно быть 47.9 (или, по крайней мере, ближайшим представимым значением fp).

Если я напишу это:

double value = 47.9;

Он корректно «привязывается» к ближайшему значению fp, которое он может получить, а именно:

47.89999999999999857891452847979962825775146484375 // fp value
101111.11100110011001100110011001100110011001100110011 // binary

Теперь предположим, что "я не пишу эти значения", но я получил их из программного обеспечения. И чем мне нужно это сломать. Я написал эту функцию:

inline double SnapValue(double value, double step) {
    return round(value / step) * step;
}

Но он возвращает эти значения:

47.900000000000005684341886080801486968994140625 // fp value
101111.11100110011001100110011001100110011001100110100 // binary

, что формально немного дальше, чем в первом примере (это «следующее» значение fp, 011 + 1).

Как бы вы получили первое значение («правильнее») для каждого входного значения?

Вот код тестирования.

ПРИМЕЧАНИЕ : шаг может быть другим - т. Е. step = 0.25 необходимо привязать значение в пределах ближайших 0,25 X. Пример: шаг 0.25 вернет значения в виде 0, 0.25 , 0.50, 0.75, 1.0, 1.25 и так далее. Таким образом, при заданном входном значении 1.30 его необходимо обернуть до ближайшего привязанного значения - то есть 1.25.

1 Ответ

0 голосов
/ 18 января 2019

Вы можете попытаться использовать рациональные значения вместо плавающей запятой. Последние часто уже неточны, поэтому на самом деле не идеальный вариант для шага.

inline double snap(double original, int numerator, int denominator)
{
    return round(original * denominator / numerator) * numerator / denominator;
}

Скажем, вы хотите шаги 0,4, затем используйте 2/5:

snap(1.7435, 2, 5) = round(4.35875) * 2 / 5 = 4 * 2 / 5 = 1.6 (or what comes closest to it)
...