2015-08-23 53 views
10

在程序中,我計算一個百分比並將其打印給用戶。問題在於打印的百分比顯示的小數過多。我搜索了一個函數來解決這個問題,沒有找到一個函數,並編程了下面的四捨五入函數,但我想知道是否有更標準的方法來做這件事。此外,this Java topic中描述的想法非常整潔,如果已經有功能可以做到這一點,我很想知道。Haskell:如何正確顯示最多兩位小數的百分比?

roundTo :: (Integral int1, Integral int2) => int1 -> Double -> Either int2 Double 
roundTo digitsAfterComma value 
    | (digitsAfterComma >= 1) = 
     let 
      factor = fromIntegral (10^digitsAfterComma) 
      result = ((/ factor) . fromIntegral . round . (* factor)) value 
     in 
      Right result 
    | (digitsAfterComma == 0) = Left (round value) 
    | otherwise = error "minimal precision must be non-negative" 

更新:更完整的版本如下,由我收到的答案開發。

import qualified Text.Printf as T 

showPercentage :: (Integral a, Show a) => a -> Double -> String 
showPercentage digitsAfterComma fraction 
    | (digitsAfterComma >= 1) = 
     let formatString = "%." ++ (show digitsAfterComma) ++ "f%%" 
     in T.printf formatString percentage 

    | (digitsAfterComma == 0) = 
     let formatString = "%d%%" 
     in T.printf formatString (round percentage :: Int) 

    | otherwise = error "minimal precision must be non-negative" 
    where percentage = 100 * fraction 

回答

11
> import Text.Printf 
> printf "%.2f" 0.22324 :: String 
"0.22" 

您可以使用most format strings C's printf supports

但請記住,Haskell的printf涉及一些複雜的類型機器,並且可能會生成難以讀取的類型錯誤。這也很一般,因爲它也可以返回IO動作,即

> printf "%.2f" 0.22324 :: IO() 
0.22 

不返回一個字符串,而是直接打印它。我建議你在每次調用printf後總是添加一個類型註釋(如上面的:: String),除非從上下文清楚了什麼是返回類型(例如,在具有其他IO操作的do塊中)。

8

printf是實心的,而另一個值得了解的庫是formatting(基於斷可愛HoleyMonoid庫):

Prelude Formatting> format ("to two decimal places: " % prec 2 % "!") 0.2222 
"to two decimal places: 0.22!" 

注意formatting是類型安全的,不像printf

Prelude Text.Printf Formatting> :t printf "%.2f" "hi" 
printf "%.2f" "hi" :: PrintfType t => t 
Prelude Text.Printf Formatting> printf "%.2f" "hi" 
*** Exception: printf: bad formatting char 'f' 

Prelude Text.Printf Formatting> :t format (prec 2) "hi" 
-- type error