例如,我有一个字符串:"6119726089.12814713"
如果我使用SISC实现(string->number "6119726089.12814713")
-,结果是6.119726089128147e9
-,在Guile实现中是6119726089.128147
,但我想要一个精确的数字,比如:611972608912814713/100000000
,而不损失精度。
我想要一个类似(string->exact)或类似这样的函数。
注意:请修复我的非母语英语并删除此消息。谢谢
使用(string->number "#e6119726089.12814713")
精确解析数字。这至少对Racket和Guile有效。然而,它可能无法在其他Scheme实现中正确工作;他们可以自由地先解析为不精确,然后转换。
下面是OP要求的string->exact
函数的可移植实现。我已经用一系列输入手动测试了它,但你应该自己测试,以确保它符合你的需求:
(define (string->exact str)
(define zero (char->integer # ))
(let loop ((result #f)
(factor 1)
(seen-dot? #f)
(digits (string->list str)))
(if (null? digits)
(and result (/ result factor))
(let ((cur (car digits))
(next (cdr digits)))
(cond ((and (not result) (not seen-dot?) (char=? cur #-))
(loop result (- factor) seen-dot? next))
((and (not seen-dot?) (char=? cur #.))
(loop result factor #t next))
((char<=? # cur #9)
(loop (+ (* (or result 0) 10) (- (char->integer cur) zero))
(if seen-dot? (* factor 10) factor)
seen-dot? next))
(else #f))))))