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