Now there are before there were not.
Am 27.02.2017 10:07 schrieb "Lindsay John Lawrence" <
lawrence.lindsayj...@gmail.com>:

> Hi,
>
> Are there scaled (fixed point) versions of division and sqrt in picolisp?
> I may have missed them..
>
> In any event I wrote a couple of functions to provide that functionality
> that may be useful to others as well. Performance is reasonable.
>
> It is quite nice to be able to be able to do arbitrary precision
> arithmetic in this way =)
>
> /Lindsay
>
> Code:
>
> # Scaled fixed point long division. (if necessary, round last digit)
> # TODO: Brute force implementation...
> #       There is probably a better way to do it.
> : (pp '/*)
> (de /* (N D S)
>    (let (Q NIL  R NIL  Acc NIL  Cnt 0)
>       (default S *Scl)
>       (setq S (+ 2 S))
>       (do S
>          (T (>= Cnt S))
>          (setq
>             Q (/ N D)
>             R (% N D)
>             Acc (cons Q Acc)
>             Cnt (inc Cnt)
>             N R )
>          (when (and (gt0 N) (<= N D))
>             (while (and (gt0 N) (<= N D))
>                (setq
>                   N (* N 10)
>                   Acc (cons 0 Acc)
>                   Cnt (inc Cnt) ) )
>             (pop 'Acc)
>             (dec 'Cnt) ) )
>       (setq R (pop 'Acc))
>       (if (<= 5 R)
>          (setq Acc (cons (+ 1 (pop 'Acc)) Acc)) )
>       (setq Acc (flip Acc))
>       (format
>          (pack (cons (car Acc) "." (cdr Acc)))
>          (- S 2) ) ) )
> -> /*
>
> # Scaled fixed point sqrt(); no rounding
> # TODO: Converges in 4-7 iterations in tests, 13 is probably overkill
> : (pp 'sqrt*)
> (de sqrt* (N S)
>    (let (P (/ N 2)  M 13)
>       (default S *Scl)
>       (setq N (* N (** 10 S)))
>       (while (ge0 (dec 'M))
>          (setq P (/ (+ P (/ N P)) 2)) )
>       P ) )
> -> sqrt*
>
>
>
> Some Tests:
>
> # Arbitrary Fixed Precision Square Root
> # Compare: bc.
> # also: https://apod.nasa.gov/htmltest/gifcity/sqrt2.1mil
> : (scl 64) (format (sqrt* 2.0) *Scl)
> -> "1.4142135623730950488016887242096980785696718753769480731766797379"
> : (scl 64) (format (sqrt* 0.5) *Scl)
> -> "0.7071067811865475244008443621048490392848359376884740365883398689"
> : (scl 64) (format (sqrt* 9967.0) *Scl)
> -> "99.8348636499294268455686673311236280296661789737252407300182230035"
> : (scl 100000) (bench (nil (sqrt* 2.0)))
> 2.027 sec
>
> # Arbitrary Fixed Precision Long Division
> # Compare: bc e.g. "scale=64 1/9967"
> : (scl 64) (/* 1.0 9967.0)
> -> 1003310926055984749673923949031804956355974716564663389184308
> : (scl 64) (format (/* 1.0 9967.0) *Scl)
> -> "0.0001003310926055984749673923949031804956355974716564663389184308"
> : (scl 64) (format (format (/* 1.0 9967.0) *Scl) *Scl)
> -> 1003310926055984749673923949031804956355974716564663389184308
> : (scl 32) (/* 22.0 7.0)
> -> 314285714285714285714285714285714
> : (scl 0) (/* 22.0 7.0)
> -> 3
> : (scl 1) (/* 22.0 7.0)
> -> 31
> : (scl 8) (/* 22.0 7.0)
> -> 314285714
> : (scl 32) (/* 1.0 3.0)
> -> 33333333333333333333333333333333
> : (scl 32) (/* 10.0 3.0)
> -> 333333333333333333333333333333333
> : (scl 32) (format (/* 1.0 3.0) *Scl)
> -> "0.33333333333333333333333333333333"
> : (scl 32) (format (/* 10.0 3.0) *Scl)
> -> "3.33333333333333333333333333333333"
> : (scl 32) (format (/* 0.22 0.7) *Scl)
> -> "0.31428571428571428571428571428571"
> : (scl 32) (format (/* 9968.0 32.0) *Scl)
> -> "311.50000000000000000000000000000000"
> : (scl 10000) (bench (nil (format (/* 1.0 9967.0) *Scl)))
> 7.685 sec
>

Reply via email to