Umwandlung von Integer in die Liste stellen, ohne 'mod' und 'div'
Momentan habe ich die Haskell-Funktion wandelt eine ganze Zahl in eine Liste von Ziffern genommen von der ursprünglichen ganzen Zahl. Meine Frage ist also: gibt es eine Möglichkeit, dies zu tun, ohne mit mod
und div
? Zum Beispiel, wenn ich wollte, das gleiche zu tun, nur mit einem string könnte ich eine Funktion erstellen, die Nutzung anderer Funktionen, wie Kopf und Schwanz usw.
Ich kämpfte mit diesem problem für eine Weile, bevor Sie schließlich kommen, um SO und finden die Antwort in einem anderen post. Was hat mich diese Frage ist die Tatsache, dass ich hätte nie daran gedacht, mit mod
und div
mich!
toDigits :: Integer -> [Integer]
toDigits n
| n < 1 = []
| otherwise = toDigits (n `div` 10) ++ [n `mod` 10]
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sie erwähnt, dass Sie das gleiche tun könnte auf strings mit einer Liste von Operationen. In der Tat, das wäre eine andere Art und Weise. Sie könnte konvertieren von integer in string umwandeln und dann jedes Zeichen in eine Ganzzahl:
Hier habe ich
Int
eher alsInteger
, aber Sie könnenInteger
wenn Sie wirklich wollen, mit ein wenig mehr Mühe:@icktoofay Antwort verwendet
show
, eine generische Art und Weise zu konvertieren einen Wert zu einemString
(in anderen Worten, seine string-Darstellung). Ein Wert sollte von einem Typ, der eine Instanz einer typeclassShow
. Zum BeispielInt
ist eine Instanz vonShow
(geben Sie:i Int
imghci
und suchen nach einer Zeichenfolgeinstance Show Int -- Defined in `GHC.Show'
). Aber eine Funktion ist nicht eine Instanz vonShow
, solet f n = n in f
wirft einen Fehler, denn wie würde Sie konvertieren eine Funktion, um einen string? (Siehe auch: Wenn Funktionen als Instanzen der Show typeclass). Wie auch immer, mitshow
Funktion ist idiomatischer, so können Sie sich auch daran halten.Es ist jedoch ein Verfahren zum extrahieren einer Ziffer aus einer Zahl mithilfe von Logarithmen, Potenzen und integer-Divisionen. Denken Sie daran, dass Sie können entfernen Sie die Ziffern aus der linken von der Suche nach einem Rest, und entfernen Sie die Ziffern von rechts durch integer-division. In beiden Fällen, der Rechte operand ist einige Kraft der 10. Zum Beispiel:
Aber wie wollen Sie wissen, welche Potenz von 10, die Sie verwenden sollten, durch die geteilt werden? Von der Suche nach einem Logarithmus zur Basis 10: #Ziffern von N = log10N + 1, z.B. log1012345 = 4. Leider können Sie nicht verwenden,
logBase
, weil es verwendet floating-point-Arithmetik, die ungenau. Zum Beispiel:Können Sie benutzerdefinierte Funktion
iLogBase
für Ganzzahlen kopieren Sie den code aus dem link in Ihren Quellcode. Auf diese Weise finden Sie eine erste Ziffer einer Zahl, die ich den folgenden code verwenden:Erstellen eine mehr Allgemeine Funktion bei der Suche nach einer beliebigen Ziffer der einen Zahl und der Umwandlung einer Zahl in eine Liste von Ziffern ist Links, um Sie als übung :).
Darüber hinaus ist der code in deiner Frage ist ineffizient. Liste Verkettung
(++)
operation hat die Komplexität derO(n)
, das heißt, jedes mal, wenn Sie wollen, um ein element anzuhängen und am Ende der Liste, es hat der linken Liste in die Rechte Liste, bis Sie die resultierende Liste. Überprüfen Sie heraus die Quelle für(++)
im Grunde[1,2,3] ++ [4]
wird1 : 2 : 3 : [4]
, das ist furchtbar ineffizient, da dauert es 3 Nachteile(:)
Operationen zum hinzufügen einer Liste. Und als Sie Anhängen von zahlen an das Ende mehrmals, es zu wiederholen Sie den gleichen Vorgang jedes mal, also insgesamt die Komplexität der Funktion istO(n^2)
.Auf der anderen Seite
(:)
ist instant, das heißt, hat die Komplexität derO(1)
. Egal wie lange ist Ihre Liste voranstellen eines Elements am Anfang ist Billig. Also anstatt das hinzufügen eines Elements zu Ende ist, würde ich empfehlen, indem es um den Anfang und das Ende einfach nur die Umkehrung der Liste wieder (für Informationen, die Lisp-Leute nennen diese push/nreverse idiom):