当前位置:  开发笔记 > 编程语言 > 正文

quotRem和divMod之间的区别何时有用?

如何解决《quotRem和divMod之间的区别何时有用?》经验,为你挑选了3个好方法。

来自haskell报告:

如果y不为零,则quot,rem,div和mod类方法满足这些定律:

(x `quot` y)*y + (x `rem` y) == x
(x `div`  y)*y + (x `mod` y) == x

quot是整数除法被截断为零,而结果div 被截断为负无穷大.

例如:

Prelude> (-12) `quot` 5
-2
Prelude> (-12) `div` 5
-3

结果如何截断的区别在哪里?



1> ShreevatsaR..:

许多语言都有一个"mod"或"%"运算符,它在除法后给出余数,截断为0; 例如C,C++和Java,可能还有C#,会说:

(-11)/5 = -2
(-11)%5 = -1
5*((-11)/5) + (-11)%5 = 5*(-2) + (-1) = -11.

Haskell的quotrem旨在模仿这种行为.我可以想象在一些人为的情况下,可能需要与某些C程序的输出兼容.

Haskell的divmod,随后Python的/和%,跟随数学家(至少数理论家)的约定,始终截断下来师(不计入0 -接近负无穷大),这样的形式始终是负数.因此在Python中,

(-11)/5 = -3
(-11)%5 = 4
5*((-11)/5) + (-11)%5 = 5*(-3) + 4 = -11.

Haskell divmod遵循这种行为.


"所以余数总是非负的"技术上,"mod"的符号遵循第二个操作数的符号.
@luqui:不,这不能解释.你总是可以得到x = q*y + r,其中r是非负的; 例如,如果`divMod 11(-5)=(-2,1)`(而不是(-3,-4)),你仍然有"11 =( - 2)*( - 5)+ 1".所以你的条件不强制`mod`的符号跟随第二个操作数.顺便说一下,`x = q*y + r`的属性也总是对于quotRem是真的,并且总是有无数对(q,r)使得`x = q*y + r`(恰好两个这些对有| r | 实际上,虽然C99和C++ 11确实指定了截断到0的定义,但是早期的版本使其保留了实现定义,因此"与C的兼容性"是其他语言或程序不太可能(或至少是坏...)的原因.截断到0.

2> luqui..:

这不完全是你问题的答案,但在x86上的GHC中,Int上的quotRem将编译为单个机器指令,而divMod则做了相当多的工作.因此,如果您处于速度关键部分并且只处理正数,那么可以使用quotRem.


为了解决SPOJ素数,使用rem而不是mod使我的测试文件运行在4.758s而不是5.533s.这意味着在32位Ubuntu,Haskell Platform 2011下,更快版本的速度提高了16%.

3> namin..:

一个简单的例子就是测试整数是偶数还是奇数.

let buggyOdd x = x `rem` 2 == 1
buggyOdd 1 // True
buggyOdd (-1) // False (wrong!)

let odd x = x `mod` 2 == 1
odd 1 // True
odd (-1) // True

当然,请注意,您可以通过以这种方式定义odd来避免考虑这些问题:

let odd x = x `rem` 2 /= 0
odd 1 // True
odd (-1) // True

一般来说,只要记住,因为y > 0,x mod y总是返回一些东西,>= 0同时x rem y返回0或与x相同的符号.

推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有