2

我有一个在.NET 中处理一些地理坐标的方法,并且我有一个存储坐标对的结构,如果为其中一个坐标传入 256,则它变为 0。但是,在一个特定实例中,值为大约 255.99999998 被计算出来,因此存储在结构中。当它在 ToString() 中打印时,它变成 256,这不应该发生 - 256 应该是 0。我不介意它是否打印 255.9999998,但是当调试器显示 255.99999998 时它打印 256 是一个问题。让它同时存储和显示 0 会更好。

具体来说,比较存在问题。255.99999998 足够接近 256 以至于它应该等于它。比较双打时应该怎么做?使用某种 epsilon 值?


编辑:具体来说,我的问题是我取一个值,执行一些计算,然后对该数字执行相反的计算,我需要准确地取回原始值。

4

4 回答 4

3

这听起来像是数字如何打印的问题,而不是如何存储的问题。Adouble有大约 15 个有效数字,因此它可以精确地从 256 中分辨出 255.99999998。

于 2010-06-23T01:37:42.523 回答
1

您可以选择格式字符串,这样您就可以根据需要显示尽可能多的数字。

比较双精度值是否相等的常用方法是减去它们,看看绝对值是否小于某个预定义的 epsilon,可能是 0.000001。

于 2010-06-23T01:41:41.403 回答
1

您可以使用 epsilon 方法,但 epsilon 通常是一种软糖,可以绕过浮点运算有损这一事实。

您可能会考虑完全避免使用二进制浮点并使用一个不错的 Rational 类。

如果您像使用 Rational 类型那样进行无损算术,那么上面的计算可能注定是 256。

有理类型可以使用 Ratio 或 Fraction 类的名称,并且编写起来相当简单

这是一个例子。这是另一个


编辑....

要理解您的问题,请考虑当十进制值 0.01 转换为二进制表示时,它不能完全存储在有限内存中。该值的十六进制表示为 0.028F5C28F5C,其中“28F5C”无限重复。因此,即使在进行任何计算之前,只需将 0.01 以二进制格式存储,您就会失去准确性。

Rational 和 Decimal 类被用来克服这个问题,尽管有性能成本。有理类型通过存储分子和分母来表示您的值来避免这个问题。十进制类型使用二进制编码的十进制格式,除法可能有损,但可以准确存储常见的十进制值。

出于您的目的,我仍然建议使用 Rational 类型。

于 2010-06-23T01:53:39.033 回答
0

您必须自行决定两个值相等的阈值。这相当于使用所谓的定点数(与浮点数相反)。然后,您必须手动执行四舍五入。

我会使用一些已知大小的无符号类型(例如 uint32 或 uint64,如果它们可用,我不知道 .NET)并将其视为定点数类型 mod 256。

例如。

typedef uint32 fixed;

inline fixed to_fixed(double d)
{
    return (fixed)(fmod(d, 256.) * (double)(1 << 24))
}

inline double to_double(fixed f)
{
    return (double)f / (double)(1 << 24);
}

或更精细的东西以适应舍入约定(最接近,更低,更高,奇数,偶数)。fixed 的最高 8 位保存整数部分,低 24 位保存小数部分。绝对精度为 2^{-24}。

请注意,添加和减去这些数字自然会在 256 处折回。对于乘法,您应该小心。

于 2010-06-24T18:44:13.057 回答