You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Haskell中实现类似JavaScript的取模(支持非整数与符号)?

实现与JavaScript一致的Haskell取模函数

JavaScript的取模行为

JavaScript中%运算符的结果符号与被除数一致,具体行为如下:

console.log(13 % 5);
// Expected output: 3

console.log(-13 % 5);
// Expected output: -3

我需要在Haskell中实现完全相同的逻辑,目前编写了以下代码:

:{
modulo :: Double -> Int -> Double
modulo a p = 
    let p' = fromIntegral p
    in
    if a > 0 
        then a - fromIntegral(p * floor(a/p'))  
        else a - fromIntegral(p * ceiling(a/p'))
:}

这段代码能得到和JavaScript一致的结果,但我想知道有没有更简洁高效的实现方式。需要注意的是,该函数必须支持Double类型的被除数a,和Haskell内置的rem不同,比如:

ghci> modulo (-13.5) 5
-3.5

更简洁的实现方式

JavaScript的%本质是余数运算,结果符号与被除数一致,等价于公式:a - b * Math.trunc(a / b)。对应到Haskell中,Math.trunc可以用truncate函数实现,因此可以简化代码为:

modulo :: Double -> Int -> Double
modulo a p = let p' = fromIntegral p
             in a - p' * fromIntegral (truncate (a / p'))

测试验证

  • 正数场景:modulo 13 5 → 13 - 5 * truncate(2.6) → 13-10=3,符合预期。
  • 负数被除数场景:modulo (-13) 5 → -13 -5 * truncate(-2.6) → -13 +10=-3,符合预期。
  • 小数被除数场景:modulo (-13.5)5 → -13.5 -5 * truncate(-2.7) → -13.5+10=-3.5,符合预期。

如果需要支持更多数值类型(比如Float作为被除数,Integer作为除数),可以泛化类型签名:

modulo :: (RealFrac a, Integral b) => a -> b -> a
modulo a p = let p' = fromIntegral p
             in a - p' * fromIntegral (truncate (a / p'))

内容的提问来源于stack exchange,提问作者Stéphane Laurent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:36:21