Floating point 如何使用float_of_int在Ocaml中获得一个自然整数作为小数点后的新数字?

Floating point 如何使用float_of_int在Ocaml中获得一个自然整数作为小数点后的新数字?,floating-point,integer,ocaml,Floating Point,Integer,Ocaml,我想要什么? let rec getDecFrac c = if c < 1.0 then ((float_of_int c) /. (float_of_int 1)) else getDecFrac ((float_of_int c)/. (float_of_int 10));; 我想把像5这样的整数转换为0.5和12345转换为0.12345 我尝试了什么? let rec getDecFrac c = if c < 1.0 then ((float_of_int c) /.

我想要什么?

let rec getDecFrac c = if c < 1.0 then ((float_of_int c) /. (float_of_int 1)) else getDecFrac ((float_of_int c)/. (float_of_int 10));;
我想把像
5
这样的整数转换为
0.5
12345
转换为
0.12345

我尝试了什么?

let rec getDecFrac c = if c < 1.0 then ((float_of_int c) /. (float_of_int 1)) else getDecFrac ((float_of_int c)/. (float_of_int 10));;

我在做什么?

函数式编程的主要核心是将一个复杂的任务分解成一组较小的任务。我们可以看到,在数学上,
1234
0.1234
连接为
1234/10^4
,或者更一般地连接为
x/10^d(x)
,其中
d(x)
x
中的小数位数。事实上,将小数点移动一个位置等于除以十

let rec getDecFrac c = if c < 1.0 then ((float_of_int c) /. (float_of_int 1)) else getDecFrac ((float_of_int c)/. (float_of_int 10));;
让我们对它进行编码。我们如何编写
number\u of\u digits
函数?我们可以把数字转换成字符串,然后数一数字母。但事实上,它感觉很脏。让我们编写一个简单的递归算法,计算一个数字能承受的10次除法数

let rec number_of_digits x = 
  if x < 10 then 1 else 1 + number_of_digits (x/10)
看起来不错。显然,它对负数不起作用,但很容易修复(作为练习)

现在我们可以完全按照我们的数学规范来编写函数

let to_frac x = 
  float x /. 10. ** float (number_of_digits x)
并测试它是否有效

# to_frac 1234;;
- : float = 0.1234
# to_frac 0;;
- : float = 0.
# to_frac 1;;
- : float = 0.1
高级主题 当然,任何知道OCaml(以及许多其他语言,包括C/C++)中的浮点是用base 2而不是10表示的人都会惊叹这个函数不起作用。事实上,我们可以看到,并不是所有的十进制数都可以用基数为2的浮点数来表示。甚至我们简单的
1234
也不是真正返回
0.1234
,而是该数字在二进制浮点数中最接近的表示形式

# printf "%.60f" (to_frac 1234);;
0.123399999999999995803356966916908277198672294616699218750000- : unit = ()

因此,请注意这一事实,特别是如果一个数字看起来像
0.1234
,它可能不是真正的
0.1234
,而是它的近似值。

如果你从一个缺少前导
0的字符串开始。
,你可以在
“0”前面加上前缀
然后使用内置的
float\u of_string
函数进行解析:

let decimals_of_string s =
  float_of_string ("0." ^ s)

您随意地混合了
float
s和
int
s。我建议最初将其实现为
float->float
,然后将其封装在一个函数中,该函数将初始的
int
转换为
float
。此外,除以
1
是毫无意义的,
float\u of_int 1=1.0
,虽然您还没有指定要它对负数做什么,我有一种感觉,它目前不符合你的意愿。我不在乎负数。我如何声明关于
float->float
删除
float\u of int
的所有用法,并使用
float
文本而不是
int
文本。如果你的意思是
让rec getdecrac c=如果c<1.0,那么c/。1其他getdecrac c/。10;;我得到了相同的错误
let decimals_of_string s =
  float_of_string ("0." ^ s)
utop # decimals_of_string "123";;
- : float = 0.123
utop # decimals_of_string "42";;
- : float = 0.42