* [Caml-list] Divide and print with precision
@ 2014-10-15 9:22 Marek Kubica
2014-10-15 10:41 ` Drup
2014-10-15 20:25 ` Török Edwin
0 siblings, 2 replies; 5+ messages in thread
From: Marek Kubica @ 2014-10-15 9:22 UTC (permalink / raw)
To: caml users
Hello,
I've got this short program here:
let prec = 1_000_000
let max_n = 205_211
let to_string = Gmp.F.to_string_base_digits ~base:10 ~digits:0
let euler_fraction n =
let open Z in
let numerator = ref one in
let denominator = ref one in
for i = 1 to n do
numerator := succ (!numerator * (of_int i));
denominator := (of_int i) * !denominator;
done;
(!numerator, !denominator)
let f () =
let (num, den) = euler_fraction max_n in
let znum = Gmp.F.from_string (Z.to_string num) in
let zden = Gmp.F.from_string (Z.to_string den) in
let euler = Gmp.F.div_prec ~prec znum zden in
print_endline @@ to_string euler
let () = f ()
It just computes e, using Zarith and Gmp. While Zarith works splendid,
I am having problems getting the division to work. I mean, it does
work, but I don't know how precise it is, because I can't get mlgmp to
print the 1_000_000 digits. From what I read in the GMP docs, 0 digits
means "whatever precision is available" but even if I explicitly
specify 1000 digits or so, the output is always
"2.718281828459045235360287471352662497757E0".
What can I do to get longer output? I don't insist on mlgmp (in fact,
it leaks memory like crazy, before I used Zarith I used mlgmp which
used 12 GB of RAM before I killed it), I just want some way to get a
base-10 floating point representation of my number.
Hope someone knows a solution.
regards,
Marek
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Divide and print with precision
2014-10-15 9:22 [Caml-list] Divide and print with precision Marek Kubica
@ 2014-10-15 10:41 ` Drup
2014-10-15 11:13 ` Marek Kubica
2014-10-15 20:25 ` Török Edwin
1 sibling, 1 reply; 5+ messages in thread
From: Drup @ 2014-10-15 10:41 UTC (permalink / raw)
To: Marek Kubica, caml users
Why do you use Gmp ? Zarith already uses GMP under the hood and you can
use the Q module for arbitrary precision rationals.
Le 15/10/2014 11:22, Marek Kubica a écrit :
> Hello,
>
> I've got this short program here:
>
> let prec = 1_000_000
> let max_n = 205_211
> let to_string = Gmp.F.to_string_base_digits ~base:10 ~digits:0
>
> let euler_fraction n =
> let open Z in
> let numerator = ref one in
> let denominator = ref one in
> for i = 1 to n do
> numerator := succ (!numerator * (of_int i));
> denominator := (of_int i) * !denominator;
> done;
> (!numerator, !denominator)
>
> let f () =
> let (num, den) = euler_fraction max_n in
> let znum = Gmp.F.from_string (Z.to_string num) in
> let zden = Gmp.F.from_string (Z.to_string den) in
> let euler = Gmp.F.div_prec ~prec znum zden in
> print_endline @@ to_string euler
>
> let () = f ()
>
> It just computes e, using Zarith and Gmp. While Zarith works splendid,
> I am having problems getting the division to work. I mean, it does
> work, but I don't know how precise it is, because I can't get mlgmp to
> print the 1_000_000 digits. From what I read in the GMP docs, 0 digits
> means "whatever precision is available" but even if I explicitly
> specify 1000 digits or so, the output is always
> "2.718281828459045235360287471352662497757E0".
>
> What can I do to get longer output? I don't insist on mlgmp (in fact,
> it leaks memory like crazy, before I used Zarith I used mlgmp which
> used 12 GB of RAM before I killed it), I just want some way to get a
> base-10 floating point representation of my number.
>
> Hope someone knows a solution.
>
> regards,
> Marek
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Divide and print with precision
2014-10-15 10:41 ` Drup
@ 2014-10-15 11:13 ` Marek Kubica
0 siblings, 0 replies; 5+ messages in thread
From: Marek Kubica @ 2014-10-15 11:13 UTC (permalink / raw)
To: Drup; +Cc: caml users
Hello,
On Wed, 15 Oct 2014 12:41:12 +0200
Drup <drupyog+caml@zoho.com> wrote:
> Why do you use Gmp ? Zarith already uses GMP under the hood and you
> can use the Q module for arbitrary precision rationals.
Yes, but I couldn't find a way to print Q.t types as base 10 floating
point approximations with a certain precision.
let third = Q.(//) 1 3;;
hypothetical_print_function ~precision:1000 third;;
0.33333…33333
It might well be that I am completely overlooking something, I'm happy
if someone points me to it.
regards,
Marek
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Divide and print with precision
2014-10-15 9:22 [Caml-list] Divide and print with precision Marek Kubica
2014-10-15 10:41 ` Drup
@ 2014-10-15 20:25 ` Török Edwin
2014-10-20 21:16 ` Marek Kubica
1 sibling, 1 reply; 5+ messages in thread
From: Török Edwin @ 2014-10-15 20:25 UTC (permalink / raw)
To: caml-list
On 10/15/2014 12:22 PM, Marek Kubica wrote:
> Hello,
>
> I've got this short program here:
>
> let prec = 1_000_000
Do you mean this to be bits or digits?
AFAICT the ~prec in Gmp refers to bits.
> let max_n = 205_211
> let to_string = Gmp.F.to_string_base_digits ~base:10 ~digits:0
>
> let euler_fraction n =
> let open Z in
> let numerator = ref one in
> let denominator = ref one in
> for i = 1 to n do
> numerator := succ (!numerator * (of_int i));
> denominator := (of_int i) * !denominator;
> done;
> (!numerator, !denominator)
>
> let f () =
> let (num, den) = euler_fraction max_n in
> let znum = Gmp.F.from_string (Z.to_string num) in
> let zden = Gmp.F.from_string (Z.to_string den) in
This uses Gmp.default_prec (120 bits by default) for the conversion.
So if you want to use Gmp.F I think you have to specify the ~prec otherwise you might loose digits in the znum or zden conversion already:
let znum = Gmp.F.from_string_prec_base ~prec ~base:10 (Z.to_string num) in
let zden = Gmp.F.from_string_prec_base ~prec ~base:10 (Z.to_string den) in
let f = Gmp.F.div_prec ~prec znum zden in
Gmp.F.to_string_base_digits ~base:10 ~digits:0 f
Another possibility is to use from_q_prec. I would've used Gmp.Q.from_q_prec except for some odd reason it takes a Z.t instead of a Q.t,
so here is the code that uses Gmp.FR.from_q_prec:
let string_of_q_prec num den =
let znum = Gmp.Z.from_string (Z.to_string num) in
let zden = Gmp.Z.from_string (Z.to_string den) in
let f = Gmp.FR.from_q_prec ~prec ~mode (Gmp.Q.from_zs znum zden) in
Gmp.FR.to_string_base_digits ~mode ~base:10 ~digits:0 f
I don't really like going through string to convert from Z.t to Gmp.Z.t, there ought to be a more efficient way.
There is also Num.approx_num_fix, but if you already use Zarith/Gmp you probably don't want that.
Best regards,
--Edwin
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Divide and print with precision
2014-10-15 20:25 ` Török Edwin
@ 2014-10-20 21:16 ` Marek Kubica
0 siblings, 0 replies; 5+ messages in thread
From: Marek Kubica @ 2014-10-20 21:16 UTC (permalink / raw)
To: caml-list
Hello Török,
Sorry, I somehow missed your reply.
On Wed, 15 Oct 2014 23:25:49 +0300
Török Edwin <edwin+ml-ocaml@etorok.net> wrote:
> This uses Gmp.default_prec (120 bits by default) for the conversion.
>
> So if you want to use Gmp.F I think you have to specify the ~prec
> otherwise you might loose digits in the znum or zden conversion
> already:
>
> let znum = Gmp.F.from_string_prec_base ~prec ~base:10 (Z.to_string
> num) in let zden = Gmp.F.from_string_prec_base ~prec ~base:10
> (Z.to_string den) in let f = Gmp.F.div_prec ~prec znum zden in
> Gmp.F.to_string_base_digits ~base:10 ~digits:0 f
>
> Another possibility is to use from_q_prec. I would've used
> Gmp.Q.from_q_prec except for some odd reason it takes a Z.t instead
> of a Q.t, so here is the code that uses Gmp.FR.from_q_prec:
>
> let string_of_q_prec num den =
> let znum = Gmp.Z.from_string (Z.to_string num) in
> let zden = Gmp.Z.from_string (Z.to_string den) in
> let f = Gmp.FR.from_q_prec ~prec ~mode (Gmp.Q.from_zs znum zden) in
> Gmp.FR.to_string_base_digits ~mode ~base:10 ~digits:0 f
Thank you, that worked and outputs a lot of digits which is "good
enough" for me. Great!
For the record, here's the complete program:
let prec = 1_000_000
let max_n = 205_211
let mode = Gmp.GMP_RNDN
let euler_fraction n =
let open Z in
let numerator = ref one in
let denominator = ref one in
for i = 1 to n do
numerator := succ (!numerator * (of_int i));
denominator := (of_int i) * !denominator;
done;
(!numerator, !denominator)
let f () =
let (num, den) = euler_fraction max_n in
let znum = Gmp.Z.from_string @@ Z.to_string num in
let zden = Gmp.Z.from_string @@ Z.to_string den in
let euler = Gmp.FR.from_q_prec ~mode ~prec @@ Gmp.Q.from_zs znum zden
in
print_endline @@ Gmp.FR.to_string_base_digits ~mode ~base:10
~digits:0 euler
let () = f ()
> I don't really like going through string to convert from Z.t to
> Gmp.Z.t, there ought to be a more efficient way.
Neither do I, but I suppose I'd need a C stub to take the Z.t value
(which if I understand Zarith correctly can be a GMP value, but for
small values isn't) and convert it into a Gmp.Z.t. But for such a
simple program and a constant amount of conversions, its not really
worth it.
regards,
Marek
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2014-10-20 21:19 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-15 9:22 [Caml-list] Divide and print with precision Marek Kubica
2014-10-15 10:41 ` Drup
2014-10-15 11:13 ` Marek Kubica
2014-10-15 20:25 ` Török Edwin
2014-10-20 21:16 ` Marek Kubica
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox