任何人都可以解释以下内容,这对我来说只是一个错误:
select convert(numeric(8,4), convert(float, '12.4155499999999996418864611769'))
12.4156
肯定答案应该是12.4155。 为了仔细检查,我创建了一个表MyTab,其中包含一个sybase“float”列,并插入了“12.4155499999999996418864611769”。然后使用转换转储十六进制并得到0x4028D4C2F837B4A2。这确实是我插入的字符串的IEEE 754双精度表示。然后,如果我(如上所述)将其转换为数字(8,4),则给出12.4156。
这是错误的,因为我认为是这样,还是我生气了?
答案 0 :(得分:6)
您可能在Sybase中从双精度到十进制的转换中遇到double-rounding错误。
使用的算法很可能是首先打印IEEE 754编号(在您的情况下,由0x4028D4C2F837B4A2表示),例如,精确到17位十进制数字,因为这个位数在某种意义上是IEEE 754双精度格式的“十进制精度”。对于您的示例,此转换为十进制的结果为12.415550000000000。
然后,由于你在点之后要求4个十进制数字,所以中间十进制表示将四舍五入到它,在tie-go-up或tie-go-to-nearest-even下。两者都是错的,因为第一轮舍入已经失去了一些关键信息(即原始数字略低于12.41555,不完全是这样)。
我不熟悉Sybase,但很可能没有简单的解决方法。您可能需要转换为带有足够无关数字的十进制数以避免问题(即21个额外数字,见下文)但您可以预期17日之后的数字打印为“0”,原因与您获得双倍相同首先是十进制转换。您可以从您的双精度数中减去12(该操作恰好是精确的,即不引入任何近似值),以便在转换为十进制中获得几位数,但这不足以确保正确舍入所有双精度值。
作为参考,我们所讨论的双精度数的确切值是12.415549999999999641886461176909506320953369140625。
根据Mark Dickinson的答案,对于第一次转换,转换超过20次十进制数字超过第二次舍入所需的十进制数字将使结果免受“双舍入”的任何明显影响。 this question。在你的问题的数量是连续花枝招展的在双的最大数量一个很好的候选人,但在马克的2.12818792307269553358078502102171540639252016258831784842556110831434197718043638405555406495645619729155240037555858106390933161420388023706431461384056688295540725831155392678607931808851292893574214797681879999999999999999999941026584542575391157788777223962620780080784703190447744595561259568772261019375946489162743091583251953125E-122的前相形见绌。