caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [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;
as well as URLs for NNTP newsgroup(s).