【问题标题】:Is there a Method for Math division without Rounding errors?有没有无舍入误差的数学除法方法?
【发布时间】:2026-01-10 22:55:02
【问题描述】:

有没有一种完全消除除法舍入误差的数学计算方法?

我正在尝试即时计算传感器输出的平均值,但经过数百万次迭代后,由于舍入误差,我的平均值正在漂移。

目前我将我的值存储在内存中,这可以正常工作,但会以内存/性能为代价。

EG

int number1 = 10;
int number2 = 3;
Console.WriteLine((number1/number2));

结果 = 3 (3.333~!)

float number1 = 10
float number2 = 3
Console.Writeline((number1/number2))

结果 = 3.33333325 (3.3~)

示例来自:https://docs.microsoft.com/en-us/dotnet/api/system.decimal?view=netcore-3.1

decimal dividend = Decimal.One;
decimal divisor = 3;
Console.WriteLine(dividend/divisor * divisor);

结果 = 0.9999999999999999999999999999 而不是 1(!!!)

这对我的应用程序来说是一个巨大的问题,因为我不断地将除法计算应用于传感器输出,因此我的值会慢慢漂移。 Windows 计算器似乎能够解决这个问题。

是否有任何可用的解决方案或者我必须创建自己的框架?


编辑: 一个可能的解决方案可能是实现 ⅓ 的分数。否则可能需要采用不同的方法来解决问题。

【问题讨论】:

  • 听起来你想要一个支持有理算术的库。快速搜索会发现 github.com/tompazourek/Rationals 就是这样一个库。我认为 .NET 本身没有任何内容。
  • 你考虑过除之前乘吗?
  • 你明白为什么第一个代码示例的结果是3吗?
  • 10m * 3 / 3 肯定会起作用,这就是我要提出的观点。如果这还不够,请查看@JonSkeet 提供的链接。
  • the first code sample results in 3 because int cannot represent enough decimnal positions. 是 - 根据*.com/questions/10851273/…

标签: c# decimal average division


【解决方案1】:

在算术中实际上有一种方法可以解决精度问题,无需分数。但是,如果您的公式是动态的(不是硬编码的),那么它可能很难实现。否则,您可以重新安排您的操作以更精确地处理特定的数字域,例如:

(x + 1) - x 
  • 使用大浮点数时,它会变得有点 0
  • 带有小浮动 变得有点 1(小浮点数比大浮点数更精确)

所以像这样重新排列它,将在两者中给出正确的结果:

(x - x) + 1

我知道示例很简单,但是对于特定操作,您应该选择特定的重新排列,例如知道接近零的浮点数 MUCH 更精确,您可以只使用它们。在我的示例中,重新排列是为了使变量的影响最小化,因此我将它们彼此靠近,以将它们的膨胀破坏为更大、更不精确的浮点数。例如,如果我有这样的事情,我会赢:

x^1.05 + 1 - x^1.01

简单的动态方法通常是按升序对操作进行排序 - 从较低的浮点数操作到较大的浮点数。变量 x,y,z 等可大可小,因此这里有一个排序问题 - 每次在公式中传递这些变量时都要进行排序,它会为您提供最佳精度。或者您为不同的输入硬编码不同的重排排列。

这里是文章:https://books.google.ru/books?id=KJORYTHOxbEC&pg=PA390&lpg=PA390&dq=rearrange+math+operations+for+precision&source=bl&ots=y8E8fjdrYy&sig=ACfU3U1vfkonygDnLJhSCK3qh0C2kaXK3w&hl=en&sa=X&ved=2ahUKEwiv6v2Xs4PqAhXGzaQKHTTUDlwQ6AEwAHoECAgQAQ

【讨论】:

    【解决方案2】:

    十进制你一定有这样的数字问题。如果你想用更好的分数做一些计算,你应该使用任何分数库,使用分数将值保存在内存中,并且只将结果显示为小数点数。

    【讨论】:

    • 我不认为更多的分数可以为我提供合适的解决方案。我可能会尝试以 ⅓ 的方式使用分数,然后只在最后应用数学,否则我必须以不同的方式解决我的问题。
    • 只有分数才能保证在您逐一进行运算时解决除数问题。第二种解决方案是将所有数学运算保存在内存中,并以正确的数字方式求解,但实现起来要困难得多。
    • 这正是我想要克服的问题。我目前确实将所有数据存储在内存中,这会导致内存瓶颈和性能下降。我认为在计算动态值时我可以实现疯狂的性能,但代价是在数百万次操作后会出现严重漂移的值。
    最近更新 更多