如何使用 float_of_int 在 Ocaml 中的小数点后获取自然整数作为新数字?
how to get a natural int as a new number after a decimal point in Ocaml using float_of_int?
我想要什么?
我想将 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));;
我收到以下错误:
Error: This expression has type float but an expression was expected of type int
我在做什么?
函数式编程的主要优点是将复杂任务拆分为一组较小的任务。我们可以看到 1234
和 0.1234
在数学上被连接为 1234 / 10^4
或更一般地连接为 x / 10^d(x)
其中 d(x)
是 [=21= 中的小数位数].的确,小数点移动一位等于除以十
所以让我们对其进行编码。我们将如何编写 number_of_digits
函数?我们可以变脏并将数字转换为字符串并计算字母。但是,确实,它感觉很脏。让我们写一个简单的递归算法来计算一个数字可以被十除多少,
let rec number_of_digits x =
if x < 10 then 1 else 1 + number_of_digits (x/10)
看起来很简单,但不要忘记测试您的实现,
# number_of_digits 1;;
- : int = 1
# number_of_digits 1234;;
- : int = 4
看起来不错。显然它不适用于负数,但很容易修复它(留作练习),
# number_of_digits (-1234);;
- : int = 1
现在我们可以编写我们的函数,完全按照我们的数学规范,
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++)中的浮点数是使用基数 2 而不是 10 来表示的人都会惊叹这个函数不是工作。事实上,我们可以看到并不是所有的十进制数都可以使用以 2 为底的浮点数来表示。甚至我们简单的 1234
也不是真正返回 0.1234
而是最接近二进制浮点数的表示,
# printf "%.60f" (to_frac 1234);;
0.123399999999999995803356966916908277198672294616699218750000- : unit = ()
所以要注意这个事实,尤其是如果一个数字看起来像 0.1234
,它可能不是真正的 0.1234
,而只是它的近似值。
如果您从缺少前导 0.
的字符串开始,您可以在前面添加 "0."
,然后使用内置的 float_of_string
函数进行解析:
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
我想要什么?
我想将 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));;
我收到以下错误:
Error: This expression has type float but an expression was expected of type int
我在做什么?
函数式编程的主要优点是将复杂任务拆分为一组较小的任务。我们可以看到 1234
和 0.1234
在数学上被连接为 1234 / 10^4
或更一般地连接为 x / 10^d(x)
其中 d(x)
是 [=21= 中的小数位数].的确,小数点移动一位等于除以十
所以让我们对其进行编码。我们将如何编写 number_of_digits
函数?我们可以变脏并将数字转换为字符串并计算字母。但是,确实,它感觉很脏。让我们写一个简单的递归算法来计算一个数字可以被十除多少,
let rec number_of_digits x =
if x < 10 then 1 else 1 + number_of_digits (x/10)
看起来很简单,但不要忘记测试您的实现,
# number_of_digits 1;;
- : int = 1
# number_of_digits 1234;;
- : int = 4
看起来不错。显然它不适用于负数,但很容易修复它(留作练习),
# number_of_digits (-1234);;
- : int = 1
现在我们可以编写我们的函数,完全按照我们的数学规范,
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++)中的浮点数是使用基数 2 而不是 10 来表示的人都会惊叹这个函数不是工作。事实上,我们可以看到并不是所有的十进制数都可以使用以 2 为底的浮点数来表示。甚至我们简单的 1234
也不是真正返回 0.1234
而是最接近二进制浮点数的表示,
# printf "%.60f" (to_frac 1234);;
0.123399999999999995803356966916908277198672294616699218750000- : unit = ()
所以要注意这个事实,尤其是如果一个数字看起来像 0.1234
,它可能不是真正的 0.1234
,而只是它的近似值。
如果您从缺少前导 0.
的字符串开始,您可以在前面添加 "0."
,然后使用内置的 float_of_string
函数进行解析:
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