Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/100.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
Ios Swift中小数到小数的转换_Ios_Swift_Swift2_Calculator_Fractions - Fatal编程技术网

Ios Swift中小数到小数的转换

Ios Swift中小数到小数的转换,ios,swift,swift2,calculator,fractions,Ios,Swift,Swift2,Calculator,Fractions,我正在构建一个计算器,希望它能自动将每一个小数转换成小数。因此,如果用户计算的表达式的答案是“0.333333…”,它将返回“1/3”。对于“0.25”,它将返回“1/4”。使用GCD,如这里()所示,我已经找到了如何将任何以有理数结尾的十进制数转换为十进制数的方法,但这对任何重复的十进制数都不起作用(如.333333) 用于堆栈溢出的所有其他函数都在Objective-C中。但我需要在我的swift应用程序中使用一个函数!所以这个()的翻译版本会很好 任何关于如何将有理数或重复/非有理小数转换

我正在构建一个计算器,希望它能自动将每一个小数转换成小数。因此,如果用户计算的表达式的答案是“0.333333…”,它将返回“1/3”。对于“0.25”,它将返回“1/4”。使用GCD,如这里()所示,我已经找到了如何将任何以有理数结尾的十进制数转换为十进制数的方法,但这对任何重复的十进制数都不起作用(如.333333)

用于堆栈溢出的所有其他函数都在Objective-C中。但我需要在我的swift应用程序中使用一个函数!所以这个()的翻译版本会很好


任何关于如何将有理数或重复/非有理小数转换为小数的想法或解决方案(即将“0.1764705882…”转换为3/17)都将非常好

如果要将计算结果显示为有理数 然后,唯一100%正确的解决方案是在所有计算中使用有理算术,即所有中间值存储为一对整数
(分子、分母)
,所有加法、乘法、除法等都使用有理数规则完成 数字

一旦结果分配给二进制浮点数 例如,
Double
,信息丢失。比如说,

let x : Double = 7/10
x
中存储近似值
0.7
,因为该数字不能 准确地表示为一个
Double
。从

print(String(format:"%a", x)) // 0x1.6666666666666p-1
可以看到
x
保存该值

0x16666666666666 * 2^(-53) = 6305039478318694 / 9007199254740992
                           ≈ 0.69999999999999995559107901499373838305
因此,
x
作为有理数的正确表示应该是
6305039478318694/9007199254740992
,但这当然不是什么 你期待着。您所期望的是
7/10
,但还有另一个问题:

let x : Double = 69999999999999996/100000000000000000
将完全相同的值赋给
x
,它与
0.7
Double
的精度范围内

那么,
x
应该显示为
7/10
还是显示为
69999999996/1000000000000000

如上所述,使用有理算术将是完美的解决方案。 如果这是不可行的,那么您可以将
Double
转换回 具有给定精度的有理数。 (以下内容摘自)

是创建分数hn/kn(有限或无限)序列的有效方法,这些分数是给定实数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)
}
示例:

rationalApproximationOf(0.333333) // (1, 3)
rationalApproximationOf(0.25)     // (1, 4)
rationalApproximationOf(0.1764705882) // (3, 17)
rationalApproximation(of: 0.333333) // (1, 3)
rationalApproximation(of: 0.142857, withPrecision: 1.0E-10) // (142857, 1000000)
默认精度为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)

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)
}
示例:

rationalApproximationOf(0.333333) // (1, 3)
rationalApproximationOf(0.25)     // (1, 4)
rationalApproximationOf(0.1764705882) // (3, 17)
rationalApproximation(of: 0.333333) // (1, 3)
rationalApproximation(of: 0.142857, withPrecision: 1.0E-10) // (142857, 1000000)
或者——正如@brandonscript所建议的那样——使用
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)
    }
}
用法示例:

print(Rational(approximating: 0.333333))
// Rational(numerator: 1, denominator: 3)

print(Rational(approximating: .pi, withPrecision: 1.0E-7))
// Rational(numerator: 103993, denominator: 33102)
如前所述,拥有(99.99%)精确计算的唯一方法,就是从头到尾用有理数计算一切

创建这个类的原因也是因为我需要非常精确的计算,而这在swift提供的类型中是不可能的。所以我创造了我自己的类型

这是代码,我将在下面解释

class Rational {

   var alpha = 0
   var beta = 0

   init(_ a: Int, _ b: Int) {
       if (a > 0 && b > 0) || (a < 0 && b < 0) {
           simplifier(a,b,"+")
       }
       else {
           simplifier(a,b,"-")
       }
   }

   init(_ double: Double, accuracy: Int = -1) {
       exponent(double, accuracy)
   }

   func exponent(_ double: Double, _ accuracy: Int) {
       //Converts a double to a rational number, in which the denominator is of power of 10.

       var exp = 1
       var double = double

       if accuracy != -1 {
           double = Double(NSString(format: "%.\(accuracy)f" as NSString, double) as String)!
       }

       while (double*Double(exp)).remainder(dividingBy: 1) != 0 {
           exp *= 10
       }

       if double > 0 {
           simplifier(Int(double*Double(exp)), exp, "+")
       }
       else {
           simplifier(Int(double*Double(exp)), exp, "-")
       }

   }

   func gcd(_ alpha: Int, _ beta: Int) -> Int {
       // Calculates 'Greatest Common Divisor'

       var inti: [Int] = []
       var multi = 1
       var a = Swift.min(alpha,beta)
       var b = Swift.max(alpha,beta)

           for idx in 2...a {
               if idx != 1 {
                   while (a%idx == 0 && b%idx == 0) {
                       a = a/idx
                       b = b/idx
                       inti.append(idx)
                   }
               }
           }
       inti.map{ multi *= $0 }
       return multi
   }


   func simplifier(_ alpha: Int, _ beta: Int, _ posOrNeg: String) {
       //Simplifies nominator and denominator (alpha and beta) so they are 'prime' to one another.

       let alpha = alpha > 0 ? alpha : -alpha
       let beta = beta > 0 ? beta : -beta

       let greatestCommonDivisor = gcd(alpha,beta)

       self.alpha = posOrNeg == "+" ? alpha/greatestCommonDivisor : -alpha/greatestCommonDivisor
       self.beta = beta/greatestCommonDivisor
   }

}

typealias Rnl = Rational

func *(a: Rational, b: Rational) -> Rational {

   let aa = a.alpha*b.alpha
   let bb = a.beta*b.beta

   return Rational(aa, bb)

}

func /(a: Rational, b: Rational) -> Rational {

   let aa = a.alpha*b.beta
   let bb = a.beta*b.alpha

   return Rational(aa, bb)

}

func +(a: Rational, b: Rational) -> Rational {

   let aa = a.alpha*b.beta + a.beta*b.alpha
   let bb = a.beta*b.beta

   return Rational(aa, bb)

}

func -(a: Rational, b: Rational) -> Rational {

   let aa = a.alpha*b.beta - a.beta*b.alpha
   let bb = a.beta*b.beta

   return Rational(aa, bb)

}

extension Rational {

   func value() -> Double {
       return Double(self.alpha) / Double(self.beta)
   }

}

extension Rational {

   func rnlValue() -> String {

       if self.beta == 1 {
           return "\(self.alpha)"
       }
       else if self.alpha == 0  {
           return "0"
       }
       else {
           return "\(self.alpha) / \(self.beta)"
       }
   }

}

// examples:

let first = Rnl(120,45)
let second = Rnl(36,88)
let third = Rnl(2.33435, accuracy: 2)
let forth = Rnl(2.33435)

print(first.alpha, first.beta, first.value(), first.rnlValue()) // prints  8   3   2.6666666666666665   8 / 3
print((first*second).rnlValue()) // prints  12 / 11
print((first+second).rnlValue()) // prints  203 / 66
print(third.value(), forth.value()) // prints  2.33   2.33435

class理性{
varα=0
varβ=0
init(a:Int,b:Int){
如果(a>0&&b>0)| |(a<0&&b<0){
简化器(a,b,“+”)
}
否则{
简化器(a,b,“-”)
}
}
init(uuDouble:double,精度:Int=-1){
指数(双精度)
}
func指数(uu-double:double,u-accurity:Int){
//将双精度数转换为分母为10次幂的有理数。
var exp=1
var双=双
如果准确!=-1{
double=double(NSString(格式:“%.\(精度)f”作为NSString,double)作为String)!
}
while(double*double(exp))。余数(dividingBy:1)!=0{
exp*=10
}
如果double>0{
简化器(Int(double*double(exp)),exp,“+”)
}
否则{
简化器(Int(double*double(exp)),exp,“-”)
}
}
func gcd(uα:Int,uβ:Int)->Int{
//计算“最大公约数”
变量inti:[Int]=[]
多变量=1
var a=快速最小值(α,β)
var b=快速最大值(α,β)
对于2…a中的idx{
如果idx!=1{
而(a%idx==0&&b%idx==0){
a=a/idx
b=b/idx
inti.append(idx)
}
}
}
inti.map{multi*=0}
返回多个
}
func简化器(ualpha:Int,ubeta:Int,uposorreg:String){
//简化了命名和分母(alpha和beta),因此它们是彼此的“素数”。
设alpha=alpha>0?alpha:-alpha
假设beta=beta>0?beta:-beta
设最大公因子=gcd(α,β)
self.alpha=posOrNeg==“+”?alpha/greatestcommondivisior:-alpha/greatestcommondivisior
self.beta=beta/最大公因子
}
}
typealias Rnl=Rational
func*(a:Rational,b:Rational)->Rational{
设aa=a.alpha*b.alpha
设bb=a.beta*b.beta
返回理性(aa,bb)
}
func/(a:Rational,b:Rational)->Rational{
设aa=a.alpha*b.beta
设bb=a.beta*b.alpha
返回理性(aa,bb)
}
func+(a:Rational,b:Rational)->Rational{
设aa=a.alpha*b.beta+a.beta*b.alpha
设bb=a.beta*b.beta
返回理性(aa,bb)
}
func-(a:Rational,b:Rational)->Rational{
设aa=a.alpha*b.beta-a.beta*b.alpha
设bb=a.beta*b.beta
返回理性(aa,bb)
}
可拓有理数{
func value()->Double{
返回双精度(self.alpha)/双精度(self.beta)
}
}
可拓有理数{
func rnlValue()->字符串{
如果self.beta==1{
返回“\(self.alpha)”
}
如果self.alpha==0,则为else{
返回“0”
}
否则{
返回“\(self.alpha)/\(self.beta)”