owl*_*ipe 7 calculator fractions ios swift swift2
我正在构建一个计算器,并希望它自动将每个小数转换为分数.因此,如果用户计算答案为"0.333333 ..."的表达式,则返回"1/3".对于"0.25",它将返回"1/4".使用GCD,如此处所示(十进制到分数转换),我已经想出如何将任何有理的终止十进制转换为十进制,但这对任何重复的小数都不起作用(如.333333).
堆栈溢出的每个其他函数都在Objective-C中.但我需要一个快速应用程序中的功能!所以这个(/sf/answers/940116621/)的翻译版本会很棒!
关于如何将有理数或重复/无理小数转换为分数(即将"0.1764705882 ..."转换为3/17)的任何想法或解决方案都会很棒!
Mar*_*n R 38
如果要将计算结果显示为有理数,那么唯一100%正确的解决方案是在所有计算中使用有理算法,即所有中间值都存储为一对整数(numerator, denominator),所有加法,乘法,除法等都是使用有理数的规则完成.
一旦将结果分配给二进制浮点数,
例如Double,信息就会丢失.例如,
let x : Double = 7/10
Run Code Online (Sandbox Code Playgroud)
在商店x的近似的0.7,因为该数量不能精确作为表示Double.从
print(String(format:"%a", x)) // 0x1.6666666666666p-1
Run Code Online (Sandbox Code Playgroud)
人们可以看到它x具有价值
0x16666666666666 * 2^(-53) = 6305039478318694 / 9007199254740992
? 0.69999999999999995559107901499373838305
Run Code Online (Sandbox Code Playgroud)
因此,x作为一个有理数的正确表示将是
6305039478318694 / 9007199254740992,但这当然不是你所期望的.你期望的是7/10,但还有另一个问题:
let x : Double = 69999999999999996/100000000000000000
Run Code Online (Sandbox Code Playgroud)
分配完全相同的值x,它与0.7a的精度无法区分
Double.
所以应该x显示为7/10或69999999999999996/100000000000000000?
如上所述,使用有理算法将是完美的解决方案.如果这不可行,那么您可以将Double返回转换为具有给定精度的有理数.(以下内容摘自Swift的双精度LCM算法.)
连续分数 是创建(有限或无限)分数h n/k n的有效方法,它是对给定实数x的任意良好近似,这里是Swift中可能的实现:
typealias Rational = (num : Int, den : Int)
func rationalApproximationOf(x0 : Double, withPrecision eps : Double = 1.0E-6) -> Rational {
var x = x0
var a = floor(x)
var (h1, k1, h, k) = (1, 0, Int(a), 1)
while x - a > eps * Double(k) * Double(k) {
x = 1.0/(x - a)
a = floor(x)
(h1, k1, h, k) = (h, k, h1 + Int(a) * h, k1 + Int(a) * k)
}
return (h, k)
}
Run Code Online (Sandbox Code Playgroud)
例子:
rationalApproximationOf(0.333333) // (1, 3)
rationalApproximationOf(0.25) // (1, 4)
rationalApproximationOf(0.1764705882) // (3, 17)
Run Code Online (Sandbox Code Playgroud)
默认精度为1.0E-6,但您可以根据需要进行调整:
rationalApproximationOf(0.142857) // (1, 7)
rationalApproximationOf(0.142857, withPrecision: 1.0E-10) // (142857, 1000000)
rationalApproximationOf(M_PI) // (355, 113)
rationalApproximationOf(M_PI, withPrecision: 1.0E-7) // (103993, 33102)
rationalApproximationOf(M_PI, withPrecision: 1.0E-10) // (312689, 99532)
Run Code Online (Sandbox Code Playgroud)
Swift 3版本:
typealias Rational = (num : Int, den : Int)
func rationalApproximation(of x0 : Double, withPrecision eps : Double = 1.0E-6) -> Rational {
var x = x0
var a = x.rounded(.down)
var (h1, k1, h, k) = (1, 0, Int(a), 1)
while x - a > eps * Double(k) * Double(k) {
x = 1.0/(x - a)
a = x.rounded(.down)
(h1, k1, h, k) = (h, k, h1 + Int(a) * h, k1 + Int(a) * k)
}
return (h, k)
}
Run Code Online (Sandbox Code Playgroud)
例子:
rationalApproximation(of: 0.333333) // (1, 3)
rationalApproximation(of: 0.142857, withPrecision: 1.0E-10) // (142857, 1000000)
Run Code Online (Sandbox Code Playgroud)
或者 - 正如@brandonscript所建议的那样 - 使用a struct Rational和初始值设定项:
struct Rational {
let numerator : Int
let denominator: Int
init(numerator: Int, denominator: Int) {
self.numerator = numerator
self.denominator = denominator
}
init(approximating x0: Double, withPrecision eps: Double = 1.0E-6) {
var x = x0
var a = x.rounded(.down)
var (h1, k1, h, k) = (1, 0, Int(a), 1)
while x - a > eps * Double(k) * Double(k) {
x = 1.0/(x - a)
a = x.rounded(.down)
(h1, k1, h, k) = (h, k, h1 + Int(a) * h, k1 + Int(a) * k)
}
self.init(numerator: h, denominator: k)
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
print(Rational(approximating: 0.333333))
// Rational(numerator: 1, denominator: 3)
print(Rational(approximating: .pi, withPrecision: 1.0E-7))
// Rational(numerator: 103993, denominator: 33102)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4161 次 |
| 最近记录: |