Как я могу преобразовать строку в точное число в Scheme Lisp?
Например, у меня есть эта строка: "6119726089.12814713"
Если я сделаю (string->number "6119726089.12814713")
- используя реализацию SISC, результат 6.119726089128147e9
- а в Guile реализация есть 6119726089.128147
но я хотел бы точное число, как: 611972608912814713/100000000
без потери точности.
Я хотел бы функцию как (строка-> точная) или что-то вроде этого.
ПРИМЕЧАНИЕ: пожалуйста, исправьте мой не родной английский и удалите это сообщение. Благодарю.
1 ответ
Использование (string->number "#e6119726089.12814713")
разобрать число как точное. Это работает, по крайней мере, Ракет и Guile. Однако он может работать некорректно в других реализациях Схемы; они могут сначала проанализировать, как неточные, а затем обратить.
Вот портативная реализация string->exact
функция, которую попросил ОП. Я вручную проверил его с помощью ряда входов, но вы должны провести собственное тестирование, чтобы убедиться, что оно соответствует вашим потребностям:
(define (string->exact str)
(define zero (char->integer #\0))
(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<=? #\0 cur #\9)
(loop (+ (* (or result 0) 10) (- (char->integer cur) zero))
(if seen-dot? (* factor 10) factor)
seen-dot? next))
(else #f))))))