【问题标题】:Modulo operation on floating point numbers on PostgreSQLPostgreSQL上浮点数的模运算
【发布时间】:2018-11-26 18:02:21
【问题描述】:

我希望在 PostgreSQL 中执行两个浮点整数之间的模运算。具体来说,我希望强制执行角度算术,例如经过一些数学运算后,强制角度位于区间 [0,2*pi] 内。

我可以看到fmod 或 SQL 不正式支持此类。有什么合理的解决方法吗?

【问题讨论】:

  • 您使用 [0, 2π] 而不是 [−π, π] 是否有原因。后者对浮点有一些更好的属性。
  • 这些是什么?
  • 您的问题不清楚。也许 π 字符没有为您正确显示?问题是为什么你使用 [0, 2*pi] 而不是 [-π, π]?
  • 没错。问题是使用 [−π, π] 而不是 [0, 2π] 的更好属性是什么。
  • 可以在没有错误的情况下主要减少到对称间隔。为了说明,考虑两位十进制格式。如果我们将 -.012 映射到 [0, 2],最接近的可表示值是 1.9。 (确切的结果是 1.88,因为它是三位数字,所以无法表示,所以它是四舍五入的。)对于对称间隔,没有值在数量级上增加; none 从浮点格式的较精细区域(较低的指数,可表示值之间的较小步长)映射到较粗略的区域(较大的指数,较大的步长)。使用 [0, 2π],您的小负角会丢失。

标签: postgresql floating-point modulo


【解决方案1】:

自己创建这样的函数很简单:

CREATE FUNCTION fmod (
   dividend double precision,
   divisor double precision
) RETURNS double precision
    LANGUAGE sql IMMUTABLE AS
'SELECT dividend - floor(dividend / divisor) * divisor';

你可以用它来解决你的问题:

SELECT fmod(1000, 2.0 * pi());

       fmod        
-------------------
 0.973536158445768
(1 row)

这个函数可以内联,所以应该很高效。

【讨论】:

  • 舍入错误可能导致此代码的结果超出目标区间。
  • 一般来说,浮点运算是实数运算的近似值。但这也意味着必须小心使用它。当目标是将一个值减少到一个以周期为模的区间时,它应该在区间中产生一个结果。解决方案应根据需要避免或纠正舍入错误以实现该目标。正确的对称余数运算是精确的并且没有舍入误差,因为精确的数学结果是可以精确表示的。非对称余数运算需要有舍入误差,但不需要返回区间外的结果。
  • (对称余数运算返回 x-yn,其中 n 是最接近 x/y 的整数。所以它总是返回一个幅度小于或等于 x 的值,因此精确计算所需的精度答案总是可用的。对于这个不对称的余数,其中 n 是 floor(x/y),一些结果的幅度大于 x,并且在更高的二进制中,因此可用的绝对精度更低。)
猜你喜欢
  • 2021-02-20
  • 2012-03-19
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
  • 2013-06-12
  • 1970-01-01
  • 2016-08-23
相关资源
最近更新 更多