以运行时可选择的精度打印浮点数

use*_*588 5 printf ocaml

这与这个问题类似但不完全相同。

我天真地尝试过这个:

let s prec = "%." ^ (string_of_int prec) ^ "f" in
Printf.printf (s 2) 1.23
Run Code Online (Sandbox Code Playgroud)

但这被拒绝了,并被替换^^^. 有什么办法可以做到这一点吗?

ivg*_*ivg 6

由于格式字符串是类型安全的,因此它们应该在编译时已知。您不能采用任意字符串并将其用作格式字符串。此限制仍然允许您从片段构建格式,只是不要忘记调用format_of_string函数,并确保所有格式都是静态的,并且生成的格式具有相同的类型。

但是,您的特定情况已经由格式解决,因此您不需要在这里做任何花哨的事情。有*说明符,它正是您想要的:

# printf "%.*f" 10 1.0;;
1.0000000000- : unit = ()
# printf "%.*f" 1 1.0;;
1.0- : unit = ()
Run Code Online (Sandbox Code Playgroud)

它还Scanf.format_from_string允许您从动态字符串构建任意格式。以下程序演示了 OCaml 中格式的灵活性:

let () = 
  print_endline "Floating point format: ";
  let f = match read_line () with
    | "engineering" -> "%e"
    | "regular" -> "%f"
    | "pretty" -> "%g"
    | user -> user in
  let fmt =
    try Scanf.format_from_string f "%f" 
    with exn -> invalid_arg "Unrecognized format" in
  Printf.printf (fmt^^"\n") (4. *. atan 1.)
Run Code Online (Sandbox Code Playgroud)

例子:

ivg$ ocaml formats.ml 
Floating point format: 
pi = %.16f    
pi = 3.1415926535897931
Run Code Online (Sandbox Code Playgroud)

  • @ivg您可以在运行时以任何您想要的方式创建格式字符串,您不限于“组合常量字符串”。**唯一的**约束是字符串最终包含的格式与您在程序时决定的类型相匹配。例如,如果`*`不存在,那么构建`"%"就完全没问题了。^ (string_of_int width) ^ "f"` 并应用 `format_from_string`,声明它匹配 `%f`。它会匹配。 (2认同)