你如何正确地"snap"给一个值?

How do you properly "snap" to a value?

假设我在我的应用程序中设置了 0.1 步长。 所以,无论我得到什么 fp 值,我只需要逗号后的一位数字。

因此,47.93434 必须是 47.9(或至少是最接近的 fp 可表示值)。

如果我这样写:

double value = 47.9;

它正确地 "snap" 到它能得到的最接近的 fp 值,即:

47.89999999999999857891452847979962825775146484375 // fp value
101111.11100110011001100110011001100110011001100110011 // binary

现在,假设 "I don't write those values",但我是从软件中获取它们的。 而且我需要拍下它。我写了这个函数:

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

但它 return 这些值:

47.900000000000005684341886080801486968994140625 // fp value
101111.11100110011001100110011001100110011001100110100 // binary

形式上比第一个例子有点远(它的 "next" fp 值,011 + 1)。

如何获得每个输入值的第一个值("more correct")?

Here's测试代码。

注意:步骤可以不同 - 即 step = 0.25 需要将值捕捉到最接近的 0.25 X。示例:0.25 的步骤将return 值为 00.250.500.751.01.25 等。因此,给定 1.30 的输入,它需要换行到最近的捕捉值 - 即 1.25.

您可以尝试使用有理数而不是浮点数。后者通常已经不准确了,因此并不是一个理想的步骤匹配。

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)