【发布时间】:2012-12-25 15:41:54
【问题描述】:
我正在 C# 中基于 System.Int64 实现 Q31.32 fixed-point numeric type。现在我正在尝试正确地进行模运算 (%)。
我见过的所有定点算术实现都简单地根据整数模来定义 Qm.n 模,即两个 Qm.n 数字的模是它们底层整数表示的模。这在一般情况下有效,但在两种特定情况下失败:
x % y如果x == Int64.MinValue和y == -1抛出OverflowException。 我可以使用 if 语句轻松处理此问题并返回 0 这种情况,虽然这是一种奇怪的行为(unchecked在这里没有帮助)。x % y对于x和y的一些小值错误地返回0。为了 例如,如果x和y的整数表示为-413和59(十进制:~-0.000000096159 和~0,000000013737),模为0(十进制:0)而它们的十进制值的模是(根据System.Decimal) ~-0.000000013737。这个误差大约是 60 倍 类型的最大精度 (2^-32),因此不能将其视为 舍入误差。
最后一个错误的原因是什么,我可以做些什么来获得更好的准确性?
【问题讨论】:
-
你使用什么样的模除法?也许问题就在那里。要清楚(整数或定点/浮点除法?)如果您使用移位整数除法应该没有错误,在浮动除法器上,小数总是有一些错误
-
不确定你是否理解这个问题。我正在实现基于 Int64 模的定点模。一般来说,这只是工作,除了在上述情况下。你可以在这里看到实现:github.com/asik/FixedMath.Net/blob/master/Fix64.cs
-
我完全理解。我看到你使用长模数所以有两个选项 1st。长模数是错误的(不可能)或第二个。您的打印是四舍五入尝试打印 raw_values 以检查模数是否正常。在这种情况下,您需要编写自己的打印例程,该例程会更精确,或者重新配置旧的打印例程以匹配精度。
-
长模没有错,我从Fix64到十进制或双精度的转换操作也没有错。问题在于,以长模数形式实现 Q31.32 模数会导致特定值的不准确(虽然它对绝大多数值都非常有效),我不太明白为什么。
标签: c# math fixed-point