【问题标题】:Convert integer to float without precision lost将整数转换为浮点数而不会丢失精度
【发布时间】:2015-09-08 16:42:49
【问题描述】:

鉴于此代码:

#include <stdio.h>

int main()
{
    for (int i=1; i <= 10000; ++i)
    {
        printf("i= %.4lf\n", (float)i/10000);
    }
}

它会一直打印 10000 个不同的数字吗?

i= 0.0002
i= 0.0003
i= 0.0004
i= 0.0005
. . .
i= 0.9995
i= 0.9996
i= 0.9997
i= 0.0001
i= 0.9998
i= 0.9999
i= 1.0000

我想在 Oracle 数据库中插入货币值并需要一个 精确到小数点后四位。我听说 NUMBER(19,4) 数据类型在 Oracle 中保证了这种准确性,但需要确保它在我的 C 程序中得到。

我的插入语句将与此类似:

INSERT INTO PRUEBA VALUES(i/10000);

此操作可能会丢失精度吗?

谢谢,何塞·路易斯。

【问题讨论】:

  • 不要将浮点数用于货币或其他精确值。
  • @Oalf 浮点小数是一种非常可接受的表示货币的选择。
  • 我在某处发现了这个,也许它可以帮助你:What Every Computer Scientist Should Know About Floating-Point Arithmetic。我忘记是哪个帖子了...
  • @chux,只有在您不介意 float 不能准确表示所有值的情况下才可以接受,因此结果将是计算结果中的错误。
  • @chux - C float 值与您所说的这些“十进制浮点”值有什么关系?引用一个非常容易找到的谷歌热门:(spin.atomicobject.com/2014/08/14/currency-rounding-errors)“在使用货币进行任何类型的计算时,准确性非常重要。浮点数(浮点数和双精度数)没有准确的足够的表示以防止在使用货币值进行算术时累积舍入误差。"

标签: c oracle math floating-point int


【解决方案1】:

它会一直打印 10000 个不同的数字吗? --> 是的 - 使用此代码。

(float)i/100000) 会打印 100000 个不同的数字吗? --> 也许。

这将一直有效,直到代码达到float 大约 6+ 有效十进制数字的精度。这取决于FLT_DIG6 或更大。


“精确到小数点后四位。”更棘手。 float 是一个浮点数。有了它,您就有 6 个以上的有效数字,例如 1234560000.0,而不是小数点后的 4 位数字 - 这可能需要“定点”。


如果代码需要正确到 19 位的所有结果,则需要采用不同的方法。即使double 也可能无法满足编码目标,因为它至少有 10 位,通常是 15-17 位有效数字。

使用 Oracle NUMBER(19,4) 要求使用 65+ 位数。 (至少 64 位精度,1 位符号)。没有标准的 C 整数/浮点类型可以始终满足这一点。除非代码使用某种结构,否则我认为没有任何解决方案可以始终防止精度损失。

【讨论】:

    【解决方案2】:

    另一种方法是使用(隐式)定点。只需通过删除小数点来继续将您的数字表示为整数。当您需要计算中的值时,通过乘以 0.0001 来恢复它们。

    32 位整数将允许-214748.3648214748.3647 的范围,很可能太有限了。

    64 位整数将允许-922337203685477.5808922337203685477.5807 的范围。

    请注意,这比存储在双精度浮点数中的精度更高,因此您应该确定所需的实际范围和要支持的算术运算。

    【讨论】:

      猜你喜欢
      • 2011-05-26
      • 1970-01-01
      • 2018-08-02
      • 2011-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 2012-10-26
      相关资源
      最近更新 更多