2
votes

Conversion binaire intégrée dans Scheme / Lisp

Existe-t-il une fonction de conversion binaire en décimale intégrée dans Scheme?

J'ai trouvé la conversion intégrée number-> string qui peut convertir le binaire en forme décimale.

Cependant, le string-> number opposé ne convertit pas les décimales en chaîne binaire comme je le pensais.

Existe-t-il une fonction intégrée ou devrions-nous la définir?


0 commentaires

4 Réponses :


5
votes

La fonction string-> number accepte un paramètre radix facultatif:

(string->number "1001" 2)
==> 9


0 commentaires

5
votes

Le binaire et le décimal sont des représentations de nombres; les nombres eux-mêmes ne sont ni binaires ni décimaux.

number-> string convertit d'un nombre (tel que douze) en une chaîne (telle que "12"), générant par défaut la représentation en base 10 du nombre .
(Il ne convertit pas de binaire en décimal - son nom décrit ce qu'il fait.)

string-> number convertit d'une chaîne (telle que "12") en un nombre (comme douze), en interprétant la chaîne comme la représentation en base 10 d'un nombre par défaut.
(Le nom de cette fonction décrit également ce qu'elle fait.)

Vous pouvez passer un deuxième argument aux deux fonctions pour une représentation de base différente (2,8,10 ou 16).

Pour obtenir une chaîne avec la représentation binaire du nombre n , utilisez (number-> string n 2) .
Pour obtenir un nombre à partir d'une chaîne s avec sa représentation binaire, utilisez (string-> number s 2) .

Exemples:

> (number->string 120)
"120"
> (string->number "120")
120
> (number->string 120 2)
"1111000"
> (string->number "1111000" 2)
120
> (number->string 120 16)
"78"
> (string->number "78" 16)
120


0 commentaires

-2
votes

Ce code a été écrit dans le schéma mit. Dans d'autres versions de lisp avec une portée statique, cela devrait également fonctionner et vous pouvez fournir une implémentation de char-> digit si une telle fonction est manquante.

(define string->number
  (lambda (ibase)
    (lambda (str)
      ((lambda (s) (s s (map (lambda (a) (char->digit a ibase)) (string->list str)) 0))
       (lambda (s input n)
         (if (null? input)
             n
             (s s (cdr input)
                (+ (car input) (* n ibase)))))))))

(define str.convert.base.16 (string->number 16))
(define str.convert.base.10 (string->number 10))
(define str.convert.base.2 (string->number 2))
(define str.convert.base.3 (string->number 3))

(str.convert.base.10 "1001")
(str.convert.base.2 "1001")
(str.convert.base.3 "1001")
(str.convert.base.16 "100")

sortie du schéma mit:

1] => (str.convert.base.10 "1001"); Valeur: 1001

1] => (str.convert.base.2 "1001"); Valeur: 9

1] => (str.convert.base.3 "1001"); Valeur: 28

1] => (str.convert.base.16 "100"); Valeur: 256


4 commentaires

char-> digit ne fait pas partie des rapports Scheme et donc votre code ne fonctionnera que dans le dialecte mit-scheme de Scheme et aucun des autres. La question n'a pas de balise mit-scheme . Procédure standard: (string-> number "100" 16); ==> 256 . Exemple tiré directement du rapport R5RS, fonctionne dans tous les rapports après.


@Sylwester Je ne suis pas sûr de ce que vous voulez dire, mais n'hésitez pas à utiliser ((string-> number 16) "100") pour obtenir 256. Si vous n'avez pas dans une implémentation char-> digit n'hésitez pas à le mettre en œuvre.


char-> digit ne fait pas partie du langage de programmation Scheme. Vous devez fournir des implémentations pour les procédures non standard dans votre réponse.


@Sylwester Je ne suis pas payé pour travailler ici;) Je ne donne qu'une courte réponse ... Je pense que tout programmeur débutant peut l'implémenter.



1
votes

Common Lisp

Comme avec Scheme, les nombres n'ont pas non plus de base en Common Lisp, seulement leurs représentations.

Visualisation d'un nombre dans une base en utilisant write-to-string :

#b1010            ; ==> 10 (base 2)
#o1010            ; ==> 520 (base 8)
#x1010            ; ==> 4112 (base 16)
#3r1010           ; ==> 30 (base 3)
#36rToBeOrNotToBe ; ==> 140613689159812836698 (base 36)

Lecture d'un nombre représenté dans une certaine base en utilisant parse-integer :

(let ((*print-base* 2))
  (prin1-to-string 10))
; ==> "1010"

(let ((*read-base* 2)) 
  (read-from-string "1010"))
; ==> 10
; ==> 5

;; *read-base* ignored when interpreted as float
(let ((*read-base* 2)) 
  (read-from-string "1010.1"))
; ==> 1010.1 
; ==> 6

Vous pouvez également utiliser le lecteur / imprimante, mais la lecture ne fonctionne que si le jeton suivant ne peut pas être interprété comme un float:

(parse-integer "1010" :radix 2)
; ==> 10
; ==> 4 (index where the parser terminated)

(parse-integer "1010.1" :radix 2) 
; parse-integer: substring "1010.1" does not have integer syntax at position 4

(parse-integer "1010.1" :radix 2 :junk-allowed t) 
; ==> 10
; ==> 4 (index where the parser terminated)

Je suppose global * print-base * et * read-base * vaut tous les deux dix. read-from-string ne se soucie pas s'il y a du courrier indésirable après le nombre donc il se comporte comme (parse-integer "1010": radix 2: junk-allowed t)

Comme info supplémentaire sur le document de base lu. Vous pouvez indiquer au lecteur les littéraux de base 2, 8 et 16 et arbitraire qui remplace le paramètre dynamique:

(write-to-string 10 :base 2)
; ==> "1010"


3 commentaires

Aussi, syntaxe du lecteur pour une base arbitraire (de 2 à 36): # 36rToBeOrNotToBe


@coredump j'ai totalement raté ça. Aimer :)


Soyez très prudent lorsque vous utilisez le lecteur sur des données que vous ne contrôlez pas entièrement, telles que les entrées utilisateur. Il est possible de configurer les choses pour que cela soit au moins sûr, mais la configuration par défaut autorise les attaques par injection de code.