Loading ...
Sorry, an error occurred while loading the content.

628Re: "ocaml_beginners"::[] Conversion of exponent number

Expand Messages
  • Danny Yoo
    Dec 1, 2002
    • 0 Attachment
      On Thu, 28 Nov 2002, Eric Merritt wrote:

      > I actually hadn't thought of that, I guess it would depend on how large
      > a number a float may store in ocaml. I will look into it.

      Hi Eric,

      The 'Num' arbitrary-precision library might also be useful if
      floating-point arithmetic isn't precise enough:

      http://caml.inria.fr/ocaml/htmlman/manual036.html


      For example:

      (******)
      # #load "nums.cma";;
      # open Num;;
      # let v = (num_of_string "9453 / 1000") */
      (num_of_int 10 **/ num_of_int 23);;
      val v : Num.num = Big_int <abstr>
      # approx_num_exp 5 v;;
      - : string = "+0.94530e24"
      (******)



      I'm still very new at this Ocaml stuff, so I'm not sure if there's a
      function in 'Num' that converts directly from scientific notation to a
      Num. But it shouldn't be too hard to cook a toy function up. Here's the
      beginnings of such a function:


      (******)

      (* string_exp_to_num: a toy example of string manipulation in Ocaml.

      Danny Yoo (dyoo@...)
      *)

      #load "nums.cma"


      let split_mantissa s =
      let s = String.lowercase s in
      let l = String.length s in
      let i = String.index s 'e' in
      let sub = String.sub in
      (sub s 0 i),
      (sub s (i+1) (l-i-1));;


      (* Given string s and integer i, returns a new string with 's'
      repeated i times. *)
      let rec string_multiply s i =
      if i = 0 then ""
      else if i mod 2 = 0
      then string_multiply (s^s) (i/2)
      else s ^ string_multiply s (i-1);;


      (* Given a decimal string, returns a string that expresses its
      ratio.*)
      let rec rationalize s =
      let i = String.index s '.' in
      let l = String.length s in
      let denom = "1" ^ (string_multiply "0" (l-i-1)) in
      (String.sub s 0 i) ^
      (String.sub s (i+1) (String.length s - i - 1))
      ^ "/" ^ denom
      ;;


      (* int_of_string does not appear to take in unary PLUS, so
      this function tries to fix that. *)
      let my_int_of_string s =
      if String.get s 0 = '+'
      then int_of_string (String.sub s 1 ((String.length s)-1))
      else int_of_string s;;



      let string_exp_to_num s =
      let (mantissa, exponent) = split_mantissa s in
      let ( * ) = Num.( */ ) in
      let ( ** ) = Num. ( **/ ) in
      (Num.num_of_string (rationalize mantissa)) *
      ((Num.num_of_int 10) ** Num.num_of_int (my_int_of_string exponent))
      ;;

      (******)


      This code is not bulletproof yet; I don't take into account things such as
      missing exponents or decimal points, but that should be pretty easy to
      patch up. It's also probably a bit ugly because I'm still learning the
      language.

      I would have expected such a function to exist in the standard library,
      since there's already a Num.approx_num_exp function that does the inverse
      operation of turning a num into a string, but I don't know enough of Ocaml
      yet.


      Good luck!
    • Show all 4 messages in this topic