Scheme 将字符串转换为方案中的十进制数

Scheme 将字符串转换为方案中的十进制数,scheme,racket,Scheme,Racket,您可以在Scheme中创建的最透明、最优雅的字符串到小数的转换过程是什么 它应该产生正确的结果,其中包括“+42”、“-6”、“-28”和“496.8128” 这是受到之前发布的整数问题列表的启发: 我的第一次尝试失败了,因为它跑得很快,我意识到其他人可能也喜欢玩它。这是第一次尝试。不难看,不漂亮,只是比我想象的要长。改天再调。我很乐意将解决方案传递给他人更好的创作 ((define (string->number S) (define (split L c) (let f

您可以在Scheme中创建的最透明、最优雅的字符串到小数的转换过程是什么

它应该产生正确的结果,其中包括“+42”、“-6”、“-28”和“496.8128”

这是受到之前发布的整数问题列表的启发:


我的第一次尝试失败了,因为它跑得很快,我意识到其他人可能也喜欢玩它。

这是第一次尝试。不难看,不漂亮,只是比我想象的要长。改天再调。我很乐意将解决方案传递给他人更好的创作

((define (string->number S)
  (define (split L c) 
    (let f ((left '()) (right L))
      (cond ((or (not (list? L)) (empty? right)) (values L #f))
            ((eq? c (car right)) (values (reverse left) (cdr right)))
            (else (f (cons (car right) left) (cdr right))))))
  (define (mkint L) 
    (let f ((sum 0) (L (map (lambda (c) (- (char->integer c) (char->integer #\0))) L)))
      (if (empty? L) sum (f (+ (car L) (* 10 sum)) (cdr L)))))
  (define list->num
    (case-lambda
      ((L) (cond ((empty? L) 0) 
                 ((eq? (car L) #\+) (list->num 1 (cdr L))) 
                 ((eq? (car L) #\-) (list->num -1 (cdr L)))
                 (else (list->num 1 L))))
      ((S L) (let*-values (((num E) (split L #\E)) ((W F) (split num #\.)))
               (cond (E (* (list->num S num) (expt 10 (list->num E))))
                     (F (* S (+ (mkint W) (/ (mkint F) (expt 10 (length F))))))
                     (else (* S (mkint W))))))))
  (list->num (string->list S)))

短得多,也使结果不精确的小数点,并处理任何+-前缀。regexp这个东西只是用来在以后假设一个有效的语法

#lang racket/base
(require racket/match)
(define (str->num s)
  ;; makes it possible to assume a correct format later
  (unless (regexp-match? #rx"^[+-]*[0-9]*([.][0-9]*)?$" s)
    (error 'str->num "bad input ~e" s))
  (define (num l a)
    (match l
      ['() a]
      [(cons #\. l) (+ a (/ (num l 0.0) (expt 10 (length l))))]
      [(cons c l) (num l (+ (* 10 a) (- (char->integer c) 48)))]))
  (define (sign l)
    (match l
      [(cons #\- l) (- (sign l))]
      [(cons #\+ l) (sign l)]
      [_ (num l 0)]))
  (sign (string->list s)))

这个问题有点模糊。你能为合法输入指定语法吗?当然。我想暗示一下。有一个可选的引导符号。有可选的数字,有可选的小数点,还有可选的附加数字。必须至少有一个数字。我不希望通过实际定义语法来删除旅程中有趣的部分。这对你有用吗?添加可选“E”和一个或多个指数数字的额外积分。允许任意基数的额外积分。哦,这不是类,堆栈溢出中没有额外的信用。顺便说一句,这意味着“”无效;我最初错误地包含了它。为什么不使用内置的
string->number
?很好,我喜欢正则表达式验证。我当时正在努力寻找提出的问题的总体解决方案。我认为使小数不精确是错误的,因为它们是定义良好的有理数。使小数不精确的一个原因是方案读者通常也这样做。在任何情况下,代码中都有一个
0.0
,您可以将其更改为
0
,使其始终精确。至于一般方案解决方案——您确实使用了
racket
标记,因此我使用了regexps和
match
;消除后者非常容易,通过将错误检查折叠到两个循环中,消除前者也不难。