Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell中计算真分数时_Haskell - Fatal编程技术网

在Haskell中计算真分数时

在Haskell中计算真分数时,haskell,Haskell,我想编写一个函数makeFraction::Float->Float->(Int,Int),每当我说makeFraction ab时,它都会返回(x,y),这样x/y就是与a/b等价的适当分数。例如,makeFraction 17.695.51应该返回(61,19) 我有一个子程序来计算两个数字的gcd,但我的第一个任务是将a和b转换为Int,例如17.69和5.51应该转换为1769和551 现在我想对任意小数位的数字做这个。前奏曲功能对我帮助不大。例如,当我说toFraction(0.2);

我想编写一个函数
makeFraction::Float->Float->(Int,Int)
,每当我说
makeFraction ab
时,它都会返回(x,y),这样x/y就是与a/b等价的适当分数。例如,
makeFraction 17.695.51
应该返回(61,19)

我有一个子程序来计算两个数字的gcd,但我的第一个任务是将a和b转换为Int,例如17.69和5.51应该转换为1769和551

现在我想对任意小数位的数字做这个。前奏曲功能对我帮助不大。例如,当我说
toFraction(0.2)
;它返回
3602879701896397%18014398509481984
,这将严重影响我以后计算的正确性

后来,我尝试通过使用另一个库函数properFraction(17.69)来获取分数值,该函数假定只给我0.69,但它产生0.69000…013,这不是我在适当的心态下会接受的

它看起来确实像是由浮点运算引起的问题。到目前为止,我并没有做任何数据操作,只是要求存储的部分位,我应该能够从处理器寄存器/内存位置获取。Haskell中是否有专门的函数库来执行这些任务


附言:这里似乎有一些有用的提示。但既然我已经打了这么多,我想把它贴出来。至少这里的上下文不同。

是的,这是您遇到的浮点运算的有限精度。浮点格式不能精确表示0.2,因此
toFraction
实际上给出了当您要求0.2时得到的浮点数的确切有理值


类似地,17.69无法精确表示,并且由于点浮动,其最佳表示的绝对误差大于0.69表示的误差。因此,当去掉整数部分时,得到的位与从一开始就要求尽可能好地表示0.69的位不同,当实现以十进制形式输出结果时,可以看到这种差异。

在我看来,与其使用浮点类型,如Float或Double,您应该使用一种能够准确表示这些数字的类型来完成所有计算,就像Rational一样。比如说,

(17.69 :: Rational) / (5.51 :: Rational)

计算为
61%19

如其他答案中所述,浮点数不一定能准确表示给定的十进制数。特别是,浮点使用
a/(2^m)
的形式存储在内部。因此,像
3/10
这样的实数只能用浮点数来近似

但如果您只需要一个合适的近似值,这可能会有所帮助:

import Data.Ratio

convertFloat :: Float -> Rational
convertFloat f = let
        denom = 10^6
        num = fromInteger denom * f
        in round num % denom
例如:

> convertFloat 17.69
1769 % 100
> convertFloat 17.69 / convertFloat 5.51
61 % 19

查看
base
的模块,尤其是功能

> floatToDigits 10 17.69
([1,7,6,9],2)

这个建议真的很好。不幸的是,函数的类型是给我的,我不允许更改它。现在的问题是“我可以从浮点表示法中恢复分数吗?”使用一些函数。@Dilawar:有一个函数
Ratio.approxRational
,它将返回数值某个半径内最简单的分数。实际上,浮点表示法有一个精确的十进制表示法。但并不是每一个十进制常数都有一个精确的浮点数表示法。谢谢,我似乎把我的措词扭曲了。我已经更新了我的答案。