2009-12-24 12 views
54

Nasıl Haskell ikili veya hex tamsayı değişmezleri yazdırmak için?nasıl Haskell ikili veya hex tamsayı değişmezleri yazdırmak için?

printBinary 5 => "0101" 

printHex 5 => "05" 

Hangi kütüphaneler/işlevler buna izin veriyor?

Ben Sayısal modülü ve showIntAtBase fonksiyonu geldi ancak doğru kullanmak sağlayamadılar. GHCi içinde

decToBin x = reverse $ decToBin' x 
    where 
    decToBin' 0 = [] 
    decToBin' y = let (a,b) = quotRem y 2 in [b] ++ decToBin' a 

kullanımını:

> :t showIntAtBase 

showIntAtBase :: (Integral a) => a -> (Int -> Char) -> a -> String -> String 

cevap

69

Sayısal modül showIntAtBase dahil olmak üzere çeşitli üslerde birkaç functions for showing an Integral type içerir. Eğer Numeric ve Data.Char modülleri içe aktarırsanız

import Numeric (showHex, showIntAtBase) 
import Data.Char (intToDigit) 

putStrLn $ showHex 12 "" -- prints "c" 
putStrLn $ showIntAtBase 2 intToDigit 12 "" -- prints "1100" 
+6

Aşağı kaydırmayan benim gibi tembel olan herkes için, printf örneği çok daha özlü ve esnek ve örn. Sabit uzunluklu bir dizi ve diğer tüm printf özelliklerini verir. Bunun yerine, yalnızca: 'printf"% 032b "5' – mozboz

+11

@mozboz, Haskell'de' printf', ciddi kodlarda kullanılan bir işlevden çok bir sihir numarası gibidir. Biçim dizgisi çalışma zamanında ayrıştırılır (çalışma zamanı hataları üretebilir) ve tüm mekanizma biraz yavaştır. – dfeuer

+0

Bu, negatif sayılarla çalışmıyor. – CMCDragonkai

3

Aşağıdaki gibi bir şey ile ikili için tamsayı dönüştürebilirsiniz

Prelude> decToBin 10 
[1,0,1,0] 
+0

Son satırın sonunda b: (decToBIn a) olması daha iyi olmaz mı? – prince

+0

0 değil 0 geri vermek? 'decToBin' 0 = [0] 'belki? – Jaseem

+0

@SjB, negatif sayılar için çalışmıyor –

26

, bunu yapabilirsiniz: İşte kullanım bazı örnekler

showIntAtBase 2 intToDigit 10 "" => "1010" 
showIntAtBase 16 intToDigit 1023 "" => "3ff" 

bu her olduğundan bu 16 kadar herhangi üsleri için çalışacağını intToDigit için çalışıyor. Yukarıdaki örneklerde ekstra boş bir dizgi değişkeni nedeni showIntAtBase varolan dize üzerine ekran gösterimini sıralamak olacak tip ShowS bir işlevi döndüren olmasıdır.

24

Ayrıca c tarzı biçim tanımlayıcıları ile çıkış biçimlendirmek için Printf paketinin printf kullanabilir:

import Text.Printf 

main = do 

    let i = 65535 :: Int 

    putStrLn $ printf "The value of %d in hex is: 0x%08x" i i 
    putStrLn $ printf "The html color code would be: #%06X" i 
    putStrLn $ printf "The value of %d in binary is: %b" i i 

Çıktı:

onaltılık 65535 değerdir:
0x0000FFFF html renk kodu olacaktır: # 00FFFF
ikili 65535 değerdir: 1111111111111111

+0

'printf" Onaltılık% d değeri şudur: 0x% 08x "Tamam, printf her ikisi de olabilir çünkü IO()' ve 'String' – Nybble

+0

Evet, gerçekten. Ben sadece açık yapmak istedim, bir String döndüren saf bir işlev olarak kullanılabilir. –

4

Hex ikili BinaryLiterals uzantısı gerektirdiğini 0b önek ör .:

> 0xff 
255 
>:set -XBinaryLiterals 
> 0b11 
3 

Not 0x ve ikili ile yazılabilir.

Sen gibi kendi özyinelemeli fonksiyonlar tanımlayabilir
2

:

import Data.Char (digitToInt) 
import Data.Char (intToDigit) 

-- generic function from base to decimal 
toNum :: [Char] -> Int -> (Char -> Int) -> Int 
toNum [] base map = 0 
toNum s base map = base * toNum (init(s)) base map + map(last(s)) 

-- generic function from decimal to base k 
toKBaseNum :: Int -> Int -> (Int -> Char) -> [Char] 
toKBaseNum x base map | x < base = [map x] 
         | otherwise = toKBaseNum (x `div` base) base map ++ [map(x `mod` base)] 


-- mapping function for hex to decimal 
mapHexToDec :: Char -> Int 
mapHexToDec x | x == 'A' = 10 
       | x == 'B' = 11 
       | x == 'C' = 12 
       | x == 'D' = 13 
       | x == 'E' = 14 
       | x == 'F' = 15 
       | otherwise = digitToInt(x) :: Int 

-- map decimal to hex 
mapDecToHex :: Int -> Char 
mapDecToHex x | x < 10 = intToDigit(x) 
       | x == 10 = 'A' 
       | x == 11 = 'B' 
       | x == 12 = 'C' 
       | x == 13 = 'D' 
       | x == 14 = 'E' 
       | x == 15 = 'F' 

-- hex to decimal 
hexToDec :: String -> Int 
hexToDec [] = 0 
hexToDec s = toNum s 16 mapHexToDec 

-- binary to decimal 
binToDec :: String -> Int 
binToDec [] = 0 
binToDec s = toNum s 2 (\x -> if x == '0' then 0 else 1) 

-- decimal to binary 
decToBin :: Int -> String 
decToBin x = toKBaseNum x 2 (\x -> if x == 1 then '1' else '0') 

-- decimal to hex 
decToHex :: Int -> String 
decToHex x = toKBaseNum x 16 mapDecToHex 

Açıklama: Gördüğünüz gibi, toNum fonksiyonu verilmiş tabanı ve bir eşleme fonksiyonu kullanılarak, onluya bir k tabanlı değerini dönüştürür . haritalama fonksiyonu (örn. A = 10, B = 11, ... hex için) ondalık değere özel karakterleri eşler. İkili eşleme için binToDec'te gördüğünüz gibi bir lambda ifadesi kullanabilirsiniz. toKBaseVal fonksiyonu ise

k tabanlı değerine bir ondalık dönüştürme tersidir.Yine bunun tersi olan bir eşleme fonksiyonuna ihtiyacımız var: bir ondalıktan k temelli değerin karşılık gelen özel karakterine.

bir test olarak yazabilirsiniz: haritalama basittir çünkü sadece bir lambda ifade kullanın, yine

-- decimal to octal 
decToOct :: Int -> String 
decToOct x = toKBaseNum x 8 (\x -> intToDigit(x)) 

:

binToDec(decToBin 7) = 7 

Eğer sekizlik biçime ondalık dönüştürmek istediğiniz varsayalım: sadece rakamlar.

Bu yardımcı olur umarım! İyi programlama!

İlgili konular