【问题标题】:Negative number modulo in swiftswift中的负数模数
【发布时间】:2017-05-02 00:11:37
【问题描述】:

负数的模如何在 swift 中起作用? 当我执行 (-1 % 3) 时,它给出 -1 但余数为 2。其中有什么问题?

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    Swift 余数运算符 % 计算余数 整数除法:

    a % b = a - (a/b) * b
    

    其中/ 是截断整数除法。你的情况

    (-1) % 3 = (-1) - ((-1)/3) * 3 = (-1) - 0 * 3 = -1
    

    所以余数总是与红利有相同的符号(除非 余数为零)。

    这与所需的定义相同,例如在 C99 标准中, 例如见 Does either ANSI C or ISO C specify what -5 % 10 should be?。也可以看看 Wikipedia: Modulo operation 概览 这在不同的编程语言中是如何处理的。

    在 Swift 中可以像这样定义“真正的”模数函数:

    func mod(_ a: Int, _ n: Int) -> Int {
        precondition(n > 0, "modulus must be positive")
        let r = a % n
        return r >= 0 ? r : r + n
    }
    
    print(mod(-1, 3)) // 2
    

    【讨论】:

      【解决方案2】:

      来自Language Guide - Basic Operators

      余数运算符

      余数运算符 (a % b) 计算出b 的倍数 将适合a 并返回剩余的值(称为 剩下的)。

      余数运算符 (%) 在 其他语言。然而,它在 Swift 中对负数的行为 意味着严格来说,它是余数而不是模数 操作

      ...

      计算a的余数时应用相同的方法 a的负值:

      -9 % 4   // equals -1
      

      -94 插入方程得到:

      -9 = (4 x -2) + -1
      

      给出-1的余数。

      在您的情况下,没有3 适合1,余数为1(与-1 相同 -> 余数为-1)。

      【讨论】:

      • 文档当然可以改进。 “适合-94的最大倍数”不是很清楚...
      • @MartinR 同意 :)
      【解决方案3】:

      如果您真正追求的是捕获 0 和 b 之间的数字,请尝试使用以下方法:

      infix operator %%
      
      extension Int {
          static  func %% (_ left: Int, _ right: Int) -> Int {
              if left >= 0 { return left % right }
              if left >= -right { return (left+right) }
              return ((left % right)+right)%right
          }
      }
      
      print(-1 %% 3) //prints 2
      

      这将适用于 a 的所有值,与之前的答案不同,而仅在 a > -b 时才有效。

      我更喜欢 %% 运算符,而不是仅仅重载 %,因为很明显你不是在做一个真正的 mod 函数。

      if 语句的原因,而不是仅仅使用最后的返回行,是为了速度,因为 mod 函数需要除法,而除法比条件更昂贵。

      【讨论】:

        【解决方案4】:

        一个受 cdeerinck 启发的答案,为了简单而牺牲速度,是这样的:

        infix operator %%
        
        extension Int {
        
            static  func %% (_ left: Int, _ right: Int) -> Int {
               let mod = left % right
               return mod >= 0 ? mod : mod + right
            }
        
        }
        

        我在操场上用这个小循环对其进行了测试:

        for test in [6, 5, 4, 0, -1, -2, -100, -101] {
            print(test, "%% 5", test %% 5)
        }
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-03
        • 1970-01-01
        • 1970-01-01
        • 2013-10-16
        • 2015-10-31
        • 1970-01-01
        • 1970-01-01
        • 2017-08-18
        相关资源
        最近更新 更多