是否可以计算 f# 中负数的连分数?
Is it possible to calculate the continued fraction of a negative number in f#?
我正在尝试编写一个程序来计算实数的计算分数。
它完全可以正常工作,除非我尝试对负实数执行此操作,例如“-71/23”或小数“-3,086 ...”。
如果我计算 +71/23 的连分数,我得到 [3; 11; 2].这是对的。据我所知,如果我然后尝试为 -71/23 执行此操作,我应该得到相同的 int 列表,但第一个元素为负数(通过笔和纸工作)。所以那应该是 [-3; 11; 2].
但它没有解决。我得到 [-3; -11; -1; -1],也就是每一个负数加上一个额外的负数。
我想我需要做一个分支,告诉函数只有 int 列表的第一个数字允许为负数——其余的应该返回正数。
我尝试了不同的东西,但我不确定如何解决。
顺便说一句,这是作业。
提前致谢,
斑马板
let rec float2cfrac (x : float) : int list =
let q = int x
let r = x - (float q)
match x with
| _ when r < 0.000000001 && r > -0.000000001 -> [q]
| _ when System.Math.Ceiling(x) - x <0.0001 -> [int (x + 1.0)]
| _ when q < 0 -> [-q] // this is the line where I want to do it, not sure what to do tho
| _ -> q :: float2cfrac (1.0 / r)
printfn "%A" (float2cfrac (-71.0/23.0))
编辑:移动了带有注释的代码并更改了代码格式。
编辑:经过大量工作,我现在找到了解决方案 :D 只需添加一行,说明如果 x 为负,则 -q 而不是 q :)
另请参阅下面我已接受作为答案的评论,您需要更改并添加一些功能:)
| _ when x < 0.0 -> -q :: float2cfrac (1.0 / r)
我只取绝对值,然后在末尾应用符号:
let rec float2cfrac (x : float) : int list =
let safeX = abs x
let signX = sign x
let q = int safeX
let r = safeX - (float q)
match x with
| _ when r < 0.000000001 && r > -0.000000001 -> [q]
| _ when System.Math.Ceiling(safeX) - safeX <0.0001 -> [int (safeX + 1.0)]
| _ -> q :: float2cfrac (1.0 / r)
|> List.map ( fun rawQ -> rawQ * signX )
来自 fsi:
> float2cfrac (71./23.);;
val it : int list = [3; 11; 2]
> float2cfrac (-71./23.);;
val it : int list = [-3; -11; -2]
上面的代码计算正确,但我认为问题是函数必须得到这个输出[-3; 11; 2],所以只有第一个数字是负数 :D 有什么办法吗? 已解决
当然可以。你可以用任何语言做到这一点。
一旦您知道了正有理数的系数,那么只需对其系数进行简单的操作即可将其取反。请记住,为了使其成为合法的 CF,所有拖尾系数(分号后的系数)都应为正。
然而,在进入结论之前,让我们先看看什么是负分数。设 x
为整数部分 w
和小数部分 f
的分数。我们可以这样写;
-x = w + f where 0 < f < 1
x = -w - f
然而,分数总是表示为总和,如 w + f
。我的意思是,当我们写成 2¾ 时,我们的意思是 2 + 3/4
,其中 w
是 2
,f
是 3/4
。为了将其转换为 negated 正确的求和符号,我们喜欢;
x = (-w - 1) + (1 - f)
这会产生 2¾ 的否定 (-2-1)+(1-3/4) = -3 + 1/4
对吗?
所以现在一切都很简单。我们已经将 w
部分设为 -3。因此,让我们计算 f
部分 (1/4) 的 CF 系数,它是 [0;4]
。现在显然我们只需要将 w
添加到系数的 a0
(头部)产生 [-3;4]
,作为旁注,它也等同于 [-3;3,1]
但是不要现在考虑一下。
这和上面显示的一样简单,但它变得更简单。请记住,我提到过直接操纵输入有理数的系数来取反它。为了使答案保持合理的长度,我将绕过证明,但规则是这样的;
x
是连分数,[a0; a1, a2, ...an]
是系数。然后
x = [a0, a1, a2, a3, ...] ⇒ −x = [−a0 − 1, 1, a1 − 1, a2, a3, ...]
就是这样。回到你的问题。 +71/23 实际上是 3 + 2/23,系数如 [3; 11, 2]
然后根据上述规则,否定会将其系数变成 [-3-1; 1, 11-1, 2]
即 [-4;1,10,2]
或 [-4;1,10,1,1]
.总和符号 -4 + 21/23.
注意:在上面的否定公式中,如果a1 - 1
项结果是0
(如果a1 = 1
)那么你可以消除它(0
)并将前一个值 (1
) 与下一个值 (a2
) 相加并合并它们。一般来说,任何 [a0, a1, 0, a3,..., an]
形式的连分数都应该写成 [a0,a1+a3,a4,...,an]
.
我正在尝试编写一个程序来计算实数的计算分数。 它完全可以正常工作,除非我尝试对负实数执行此操作,例如“-71/23”或小数“-3,086 ...”。
如果我计算 +71/23 的连分数,我得到 [3; 11; 2].这是对的。据我所知,如果我然后尝试为 -71/23 执行此操作,我应该得到相同的 int 列表,但第一个元素为负数(通过笔和纸工作)。所以那应该是 [-3; 11; 2]. 但它没有解决。我得到 [-3; -11; -1; -1],也就是每一个负数加上一个额外的负数。
我想我需要做一个分支,告诉函数只有 int 列表的第一个数字允许为负数——其余的应该返回正数。 我尝试了不同的东西,但我不确定如何解决。
顺便说一句,这是作业。
提前致谢, 斑马板
let rec float2cfrac (x : float) : int list =
let q = int x
let r = x - (float q)
match x with
| _ when r < 0.000000001 && r > -0.000000001 -> [q]
| _ when System.Math.Ceiling(x) - x <0.0001 -> [int (x + 1.0)]
| _ when q < 0 -> [-q] // this is the line where I want to do it, not sure what to do tho
| _ -> q :: float2cfrac (1.0 / r)
printfn "%A" (float2cfrac (-71.0/23.0))
编辑:移动了带有注释的代码并更改了代码格式。
编辑:经过大量工作,我现在找到了解决方案 :D 只需添加一行,说明如果 x 为负,则 -q 而不是 q :) 另请参阅下面我已接受作为答案的评论,您需要更改并添加一些功能:)
| _ when x < 0.0 -> -q :: float2cfrac (1.0 / r)
我只取绝对值,然后在末尾应用符号:
let rec float2cfrac (x : float) : int list =
let safeX = abs x
let signX = sign x
let q = int safeX
let r = safeX - (float q)
match x with
| _ when r < 0.000000001 && r > -0.000000001 -> [q]
| _ when System.Math.Ceiling(safeX) - safeX <0.0001 -> [int (safeX + 1.0)]
| _ -> q :: float2cfrac (1.0 / r)
|> List.map ( fun rawQ -> rawQ * signX )
来自 fsi:
> float2cfrac (71./23.);;
val it : int list = [3; 11; 2]
> float2cfrac (-71./23.);;
val it : int list = [-3; -11; -2]
上面的代码计算正确,但我认为问题是函数必须得到这个输出[-3; 11; 2],所以只有第一个数字是负数 :D 有什么办法吗? 已解决
当然可以。你可以用任何语言做到这一点。
一旦您知道了正有理数的系数,那么只需对其系数进行简单的操作即可将其取反。请记住,为了使其成为合法的 CF,所有拖尾系数(分号后的系数)都应为正。
然而,在进入结论之前,让我们先看看什么是负分数。设 x
为整数部分 w
和小数部分 f
的分数。我们可以这样写;
-x = w + f where 0 < f < 1
x = -w - f
然而,分数总是表示为总和,如 w + f
。我的意思是,当我们写成 2¾ 时,我们的意思是 2 + 3/4
,其中 w
是 2
,f
是 3/4
。为了将其转换为 negated 正确的求和符号,我们喜欢;
x = (-w - 1) + (1 - f)
这会产生 2¾ 的否定 (-2-1)+(1-3/4) = -3 + 1/4
对吗?
所以现在一切都很简单。我们已经将 w
部分设为 -3。因此,让我们计算 f
部分 (1/4) 的 CF 系数,它是 [0;4]
。现在显然我们只需要将 w
添加到系数的 a0
(头部)产生 [-3;4]
,作为旁注,它也等同于 [-3;3,1]
但是不要现在考虑一下。
这和上面显示的一样简单,但它变得更简单。请记住,我提到过直接操纵输入有理数的系数来取反它。为了使答案保持合理的长度,我将绕过证明,但规则是这样的;
x
是连分数,[a0; a1, a2, ...an]
是系数。然后
x = [a0, a1, a2, a3, ...] ⇒ −x = [−a0 − 1, 1, a1 − 1, a2, a3, ...]
就是这样。回到你的问题。 +71/23 实际上是 3 + 2/23,系数如 [3; 11, 2]
然后根据上述规则,否定会将其系数变成 [-3-1; 1, 11-1, 2]
即 [-4;1,10,2]
或 [-4;1,10,1,1]
.总和符号 -4 + 21/23.
注意:在上面的否定公式中,如果a1 - 1
项结果是0
(如果a1 = 1
)那么你可以消除它(0
)并将前一个值 (1
) 与下一个值 (a2
) 相加并合并它们。一般来说,任何 [a0, a1, 0, a3,..., an]
形式的连分数都应该写成 [a0,a1+a3,a4,...,an]
.