Jac*_*ale 1 floating-point ocaml
在Java中,如果你这样做0.2 + 0.01,你会得到0.21000000000000002
这是由于IEEE 754.
但是,在OCaml中,如果这样做0.2 +. 0.01,那么您将获得正确的结果0.21.
我认为OCaml也遵循IEEE 754 for floats,为什么OCaml可以提供正确的结果而Java不能?
cam*_*ter 10
在这种情况下哪一个是"正确的"?从浮点算术的角度来看,Java在这里是正确的.无论如何,
OCaml中顶层中的值是通过印刷genprintval.ml和有float值由印刷print_float,其使用string_of_float.其定义如下pervasives.ml:
let string_of_float f = valid_float_lexem (format_float "%.12g" f)
Run Code Online (Sandbox Code Playgroud)
如您所见,浮点数使用printf格式"%.12g"打印.小于10 ^ { - 12}的东西被简单地丢弃.这就是你看到"错误"答案的原因0.21.如果升高精度,则输出与Java相同:
# Printf.sprintf "%.20g" (0.2 +. 0.01);;
- : string = "0.21000000000000002"
Run Code Online (Sandbox Code Playgroud)
OCaml,对于它调用float的double类型,使用底层C/Unix平台的类型,该平台通常由该平台定义为IEEE 754的binary64格式.
在OCaml中,转换为十进制是以老式的方式完成的,具有固定的数字位数(camlspotter已经挖出了格式,这%.12g与OCaml中C格式具有的相同含义相同).
在现代语言(Java,Javascript,Ruby)中,时尚是通过精确地发送十进制表示所需的数字来转换为十进制,如果转换回另一个方向则转换回原始浮点数.因此在Java 0.21中打印并且仅打印double最接近0.21,这不是理性的21/100,因为这个数字不能完全表示为二进制浮点数.
一种方法并不比另一种方法好.他们都对未经警告的开发人员产生了令人惊讶的副作用.特别是,Java转换方法导致许多"为什么float我将其转换为我的更改的价值double?" 问题在StackOverflow上(答案:它没有,但由于类型包含更多,(double)0.1f因此打印了许多其他数字)价值比).0.100000doublefloat
无论如何,OCaml和Java都计算相同的浮点数0.2 + 0.01,因为它们都严格遵循IEEE 754.它们只是以不同的方式打印它们.OCaml打印固定数量的数字,这些数字不足以显示该数字既不是21/100,也不是最接近21/100的双精度浮点表示.Java打印足够的数字以显示该数字不是最接近21/100.
| 归档时间: |
|
| 查看次数: |
467 次 |
| 最近记录: |