【问题标题】:Large numbers rounding off [c#]大数四舍五入 [c#]
【发布时间】:2009-07-16 14:35:12
【问题描述】:

我在这里遇到了一些奇怪的问题。我有一个数据库表,它在列上存储了巨大的价值。我的应用程序 (C#) 正在读取这个值并保持 double 类型。此应用程序会将相同的值插入到另一个表中。注意:我没有对从第一个表中读取的值进行任何计算/处理。它只是用于更新第二个表。

这里的问题是,第二个表的值与第一个表的值略有不同。当我保持双重类型时,看起来数字正在四舍五入。

这是一个值的示例。

原始值:18014398509481984

值已复制到新表:18014398509482000

这些值看起来不同,但实际上两者都是相同的。我用 18014398509481984 - 18014398509482000 作为搜索词进行了谷歌搜索,它返回了结果 0,这意味着是一样的。

问题

1 - 如果两者相同,为什么第二个值看起来不同?我可以看到 1984 变成了 2000

2 - 为什么会发生转换?

3 - 如何避免此类转化?

任何帮助都会很棒!

【问题讨论】:

  • 第一个表中的列的类型是什么?在第二张桌子上?看起来有一个从大整数(64 位)到双精度的转换,即使没有任何处理,也会在运算中丢失精度。
  • “所有数字都是平等的”——你可以通过这种方式轻松证明——是下一次选举的绝佳平台
  • 是的,请尝试 Decimal,并检查 DB(您在那里使用哪种类型,顺便说一句?)和 .Net 类型的精度,以查看转换可能会改变值的位置
  • 使用 Windows 计算器,您可以看到数字不相等。只是 Google 与您的软件具有相同的舍入行为。当值太大而无法放入 32 位整数时(显然),它使用双精度浮点值。
  • 或者使用wolframalpha.com而不是谷歌来做数学。

标签: c# math double rounding


【解决方案1】:

尝试使用System.Decimal 来存储第一个表中的值,而不是System.DoubleSystem.Double 似乎没有足够的有效数字来准确存储这么大的值。

【讨论】:

  • 谢谢。我会尝试使用小数类型。
【解决方案2】:

双精度值仅精确到 15 或 16 位十进制数字(有关说明,请参阅 here)。如果您需要存储更多,那么您将不得不使用不同的数字格式。如果你想处理非常大的整数而不损失准确性,那么有各种类可以帮助你,比如this one

如果您从 SQL 中获取值,请确保您在 .NET 中的目标数据类型匹配 - 例如 C# long 的 SQL bigint - 以避免此类舍入问题。

【讨论】:

  • 我的表类型是 NUMBER,我使用的是 Oracle 数据库
【解决方案3】:

我相信这是由于浮点精度(大数将使用尾数和指数),这意味着它本质上将表示为具有幂的派系数。然而,小数会因浮点运算而遇到舍入错误。

通常的方法是避免浮点值(尝试 Int64),使用更精确的类型(十进制)或考虑错误并执行“近似等于”。

【讨论】:

  • 谢谢。 “大约等于”是什么意思?
  • 您可以向 Double 或静态方法添加一个扩展方法,以确定这些值之间是否为 0.001%,如果是,则假定它们相等。显然,您将阈值设置在您满意的点上。
【解决方案4】:

您需要将这些存储为浮点数吗?

如果不是,那么您可以改用 64 位整数:在数据库中使用 BIGINT,在您的应用中使用 long/Int64

它们的范围从 –9,223,372,036,854,775,808 到 9,223,372,036,854,775,807,并且没有精度/准确性问题。

【讨论】:

  • 谢谢。但我的价值将是浮点数。所以我猜 int64 或 long 不合适。
猜你喜欢
  • 1970-01-01
  • 2017-11-26
  • 1970-01-01
  • 2015-11-12
  • 2015-06-17
  • 2023-01-12
  • 2020-10-22
  • 2022-01-13
  • 1970-01-01
相关资源
最近更新 更多