div和quot之间的确切区别 [英] Exact difference between div and quot

查看:159
本文介绍了div和quot之间的确切区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这里这个问题上,两个运营商之间的差异<$ c提及$ c> div 和 quot 以及 quot 运算符比 div 运算符更高效,而 div 对我们人类来说更自然。



我的问题是两个操作符的确切实现是什么,并且链接到实现之间的区别是什么。另外,我想知道这两者之间的速度差异是如何发生的,例如使用 Hoogle 和浏览消息来源并没有帮助我寻求理解。



我想澄清一下,我理解两个操作符之间的一般区别,只对实现感兴趣,差异。

解决方案

> > div 向负无穷回合:

  div(-3)2 ==(-2) 
quot(-3)2 ==(-1)

div quot 有相应的原始GHC操作,而 div does 一些额外的工作

  quotRemInt :: Int  - > Int  - > (#q,r#) - >的情况下(Int,Int)
(I#x)`RemInt`(I#y)= case x`quotRemInt#
(I#q,I#r)

divModInt#:: Int# - > Int# - > (#Int#,Int##)
x#`divModInt#`y#
| (x#>#0#)&& (#q,r#) - >(#y#<#0#)= case(x# - #1#)`quotRemInt#`y# (#q - #1#,r +#y#+#1##)
| (x#<#0#)&& (#q,r#) - >的情况下(y#>#0#)= case(x#+#1#)`quotRemInt#`y# (#q - #1#,r +#y# - #1##)
|否则= x#`quotRemInt#`y#

在它们的最终形式中,这两个函数都有一个错误处理检查

  a`quot` b 
| b == 0 = divZeroError
| b ==(-1)&& a == minBound = overflowError - 注意[测试顺序]
- 在GHC.Int
|否则= a`quotInt` b

a`div` b
| b == 0 = divZeroError
| b ==(-1)&& a == minBound = overflowError - 注意[测试顺序]
- 在GHC.Int
|否则= a`divInt` b

我也做了很少的微基准,但它应该是因为GHC和LLVM优化紧密的数字代码,就像没有明天一样。我试图挫败他们,结果似乎是现实的: 14,67 ms div 和 13.37 ms strong> for quot 。另外,它是GHC 7.8.2的-O2和-fllvm。这里是代码:

  { - #LANGUAGE BangPatterns# - } 

import Criterion.Main
import System.Random

benchOp ::(Int - > Int) - > Int - > ()
benchOp f = go 0 0 where
go!i!acc!limit |我< limit = go(i + 1)(f i)限制
|否则=()

main = do
limit1< - randomRIO(1000000,1000000 :: Int)
limit2< - randomRIO(1000000,1000000 :: Int)
n < - randomRIO(100,100 :: Int)
defaultMain [
benchdiv$ whnf(benchOp(`div` n))limit1,
benchquot $ whnf(benchOp(`quot` n))limit2]


In this question here on SO the differences between the two operators div and quot are mentioned as well as the fact that the quot operator is more efficient than the div operator, whereas div is more natural for us humans to use.

My question is what the exact implementations of the two operators are and linked to that what the difference between implementations is. Also I want to know how the speed difference between those two comes to be, as using Hoogle and browsing the sources did not help me in my quest to understanding.

I want to clarify that I understand the general difference between the two operators and only am interested in the implementations or rather the differences.

解决方案

quot rounds towards zero, div rounds towards negative infinity:

div  (-3) 2 == (-2)
quot (-3) 2 == (-1)

As to the overhead of div, quot has a corresponding primitive GHC operation, while div does some extra work:

quotRemInt :: Int -> Int -> (Int, Int)
(I# x) `quotRemInt` (I# y) = case x `quotRemInt#` y of
                             (# q, r #) ->
                                 (I# q, I# r)

divModInt# :: Int# -> Int# -> (# Int#, Int# #)
x# `divModInt#` y#
 | (x# ># 0#) && (y# <# 0#) = case (x# -# 1#) `quotRemInt#` y# of
                              (# q, r #) -> (# q -# 1#, r +# y# +# 1# #)
 | (x# <# 0#) && (y# ># 0#) = case (x# +# 1#) `quotRemInt#` y# of
                              (# q, r #) -> (# q -# 1#, r +# y# -# 1# #)
 | otherwise                = x# `quotRemInt#` y#

In their final forms, both functions have some error handling checks on them:

a `quot` b
 | b == 0                     = divZeroError
 | b == (-1) && a == minBound = overflowError -- Note [Order of tests]
                                              -- in GHC.Int
 | otherwise                  =  a `quotInt` b

a `div` b
 | b == 0                     = divZeroError
 | b == (-1) && a == minBound = overflowError -- Note [Order of tests]
                                              -- in GHC.Int
 | otherwise                  =  a `divInt` b

I also did a very small bit of microbenchmarking, but it should be taken with a hefty amount of salt, because GHC and LLVM optimize tight numeric code away like there's no tomorrow. I tried to thwart them, and the results seem to be realistic: 14,67 ms for div and 13,37 ms for quot. Also, it's GHC 7.8.2 with -O2 and -fllvm. Here's the code:

{-# LANGUAGE BangPatterns #-}

import Criterion.Main
import System.Random

benchOp :: (Int -> Int) -> Int -> ()
benchOp f = go 0 0 where
    go !i !acc !limit | i < limit = go (i + 1) (f i) limit
                      | otherwise = ()

main = do
    limit1 <- randomRIO (1000000, 1000000 :: Int)
    limit2 <- randomRIO (1000000, 1000000 :: Int)
    n      <- randomRIO (100, 100 :: Int)
    defaultMain [
        bench "div"  $ whnf (benchOp (`div`  n)) limit1,
        bench "quot" $ whnf (benchOp (`quot` n)) limit2]

这篇关于div和quot之间的确切区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆