sybase 15.7 float 到数字舍入错误

sybase 15.7 float to numeric rounding error

任何人都可以解释以下内容,在我看来这只是一个错误:

select convert(numeric(8,4), convert(float, '12.4155499999999996418864611769'))

12.4156

当然答案应该是 12.4155。 为了仔细检查,我创建了一个 table、MyTab,其中包含一个 sybase "float" 列并插入了“12.4155499999999996418864611769”。然后使用 convert 转储十六进制并得到 0x4028D4C2F837B4A2。这确实是我插入的字符串的 IEEE 754 双精度表示。然后,如果我(如上所述)将其转换为数字(8,4),它会给出 12.4156.

这是我想的不对,还是我疯了?

您可能在 Sybase 中从双精度到十进制的转换中遇到 double-rounding 错误。

使用的算法很可能是首先打印 IEEE 754 编号(在您的情况下,由 0x4028D4C2F837B4A2 表示),例如 17 位十进制数字的精度,基于这个数字的位数是一些感知 IEEE 754 双精度格式的“小数精度”。对于您的示例,转换为十进制的结果是 12.415550000000000。

然后,由于您要求在点后输入 4 个小数位,因此中间小数表示形式四舍五入为那个,在 ties-go-up 或 ties-go-to-nearest-even 下。无论如何,两者都是错误的,因为第一轮已经丢失了一些关键信息(即,原始数字略低于 12.41555,不完全是)。

我不熟悉 Sybase,但很可能没有简单的解决方法。您可能需要使用足够多的无关数字转换为十进制以避免该问题(即 21 个额外数字,见下文)但您可以期望第 17 位之后的数字打印为“0”,原因与您得到双倍相同-首先进行四舍五入的十进制转换。您可以从您拥有的双精度数字中减去 12(该操作恰好是精确的,即不引入任何近似值)以便在转换为十进制时获得几位数字,但这不足以确保所有双精度值的正确舍入。

备注:

  1. 供参考,我们所说的双精度数的准确值为12.415549999999999641886461176909506320953369140625.

  2. 对于第一次转换,使用超出第二次舍入所需的 20 位以上的十进制数字,可以使结果免受“双舍入”的任何明显影响,根据Mark Dickinson 对 this question 的回答。 The number in your question is a good candidate for the maximum number of consecutive nines in a double, but it pales in front of Mark's 2.12818792307269553358078502102171540639252016258831784842556110831434197718043638405555406495645619729155240037555858106390933161420388023706431461384056688295540725831155392678607931808851292893574214797681879999999999999999999941026584542575391157788777223962620780080784703190447744595561259568772261019375946489162743091583251953125E-122.