Why `(map digitToInt) . show` is so fast?

前端 未结 2 1656
傲寒
傲寒 2021-02-13 22:41

Converting non-negative Integer to its list of digits is commonly done like this:

import Data.Char

digits :: Integer -> [Int]
digits = (map digi         


        
2条回答
  •  梦毁少年i
    2021-02-13 23:23

    Answering the question "why rem instead of mod?" in the comments. When dealing with positive values rem x y === mod x y so the only consideration of note is performance:

    > import Test.QuickCheck
    > quickCheck (\x y -> x > 0 && y > 0 ==> x `rem` y == x `mod` y)
    

    So what is the performance? Unless you have a good reason not to (and being lazy isn't a good reason, neither is not knowing Criterion) then use a good benchmark tool, I used Criterion:

    $ cat useRem.hs 
    import Criterion
    import Criterion.Main
    
    list :: [Integer]
    list = [1..10000]
    
    main = defaultMain
            [ bench "mod" (nf (map (`mod` 7)) list)
            , bench "rem" (nf (map (`rem` 7)) list)
            ]
    

    Running this shows rem is measurably better than mod (compiled with -O2):

    $ ./useRem 
    ...
    benchmarking mod
    ...
    mean: 590.4692 us, lb 589.2473 us, ub 592.1766 us, ci 0.950
    
    benchmarking rem
    ...
    mean: 394.1580 us, lb 393.2415 us, ub 395.4184 us, ci 0.950
    

提交回复
热议问题