Pregunta

Por ejemplo, tengo esta cadena: "6119726089.12814713"

Si hago (string->number "6119726089.12814713"), usando la implementación de SISC, el resultado es 6.119726089128147e9, y en la implementación de Greile es 6119726089.128147, pero me gustaría un número exacto, como: 611972608912814713/100000000 sin pérdida de precisión.

Me gustaría una función como (cadena-> exacta) o algo así.

NOTA: Por favor, arregle mi inglés no nativo y elimine este mensaje.Gracias.

¿Fue útil?

Solución

Use (string->number "#e6119726089.12814713") para analizar el número como exacto.Esto funciona para al menos la raqueta y la guía.Sin embargo, puede que no funcione correctamente en otras implementaciones del esquema;Están en libertad para analizar lo primero, luego convertir.


Aquí hay una implementación portátil de la función string->exact que la OP pidió.Lo he probado manualmente con una gama de insumos, pero debe hacer sus propias pruebas para asegurarse de que se ajuste a sus necesidades:

(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))))))

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top