Как преобразовать строку в точное число в Scheme Lisp?

StackOverflow https://stackoverflow.com//questions/23027030

Вопрос

Например, у меня есть эта строка:"6119726089.12814713"

Если я сделаю (string->number "6119726089.12814713") - при использовании реализации SISC результат 6.119726089128147e9 - и в Guile реализация есть 6119726089.128147 но мне бы хотелось точное число, например: 611972608912814713/100000000 без потери точности.

Мне нужна функция типа (string->exact) или что-то в этом роде.

ПРИМЕЧАНИЕ:пожалуйста, исправьте мой неродной английский и удалите это сообщение.Спасибо.

Это было полезно?

Решение

Использовать (string->number "#e6119726089.12814713") чтобы проанализировать число как точное.Это работает по крайней мере для Рэкета и Хитрости.Однако он может работать неправильно в других реализациях Scheme;они имеют право сначала проанализировать как неточные, а затем преобразовать.


Вот портативная реализация 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))))))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top