当前位置: 首页 > 面试题库 >

Swift中的小数到分数转换

乌俊健
2023-03-14
问题内容

我正在构建一个计算器,并希望它自动将每个小数
转换为分数。因此,如果用户计算出答案
为“ 0.333333…” 的表达式,它将返回“ 1/3”。对于“ 0.25”,它将返回“ 1/4”。
使用GCD(小数到小数
转换),我已经弄清楚了如何将任何有理数,终止
小数转换为小数,但这不适用于任何重复的小数
(如.333333)。

堆栈溢出的所有其他功能在Objective-C中。但是我需要
在我的快速应用程序中添加一个功能!因此,此版本的翻译版本会很不错!

关于如何将有理数或重复数/无理
数的小数转换为分数的任何想法或解决方案(例如,将“ 0.1764705882…”转换为3/17)都将是
不错的选择!


问题答案:

如果你想显示的计算,有理数的结果的话,唯一的100%正确的解决办法是使用合理的算术在所有
的计算,即所有中间值存储为一对整数(numerator, denominator),和所有加法,乘法,除法,等
有使用有理数规则完成。

一旦将结果分配给二进制浮点数(例如)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

So a correct representation of x as a rational number would be
6305039478318694 / 9007199254740992, but that is of course not what you
expect. What you expect is 7/10, but there is another problem:

let x : Double = 69999999999999996/100000000000000000

assigns exactly the same value to x, it is indistinguishable from 0.7
within the precision of a Double.

So should x be displayed as 7/10 or as
69999999999999996/100000000000000000 ?

As said above, using rational arithmetic would be the perfect solution. If
that is not viable, then you can convert the Double back to a rational
number with a given precision. (The following is taken from Algorithm for
LCM of doubles in
Swift.)

Continued Fractions are an
efficient method to create a (finite or infinite) sequence of fractions h
n/kn
that are arbitrary good approximations to a given real number x , and
here is a possible implementation in 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)
}

Examples:

rationalApproximationOf(0.333333) // (1, 3)
rationalApproximationOf(0.25)     // (1, 4)
rationalApproximationOf(0.1764705882) // (3, 17)

The default precision is 1.0E-6, but you can adjust that to your needs:

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 version:

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)
}

Examples:

rationalApproximation(of: 0.333333) // (1, 3)
rationalApproximation(of: 0.142857, withPrecision: 1.0E-10) // (142857, 1000000)

Or – as suggested by @brandonscript – with a struct Rational and an
initializer:

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)
    }
}

Example usage:

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

print(Rational(approximating: .pi, withPrecision: 1.0E-7))
// Rational(numerator: 103993, denominator: 33102)


 类似资料:
  • 我正在制作一个计算器,希望它能自动将每个小数转换成小数。因此,如果用户计算一个表达式,答案是“0.333333......”,它会返回“1/3”。对于“0.25”,它会返回“1/4”。使用GCD,如这里所示(小数到小数的转换),我已经知道如何将任何有理的、终止的小数转换成小数,但这对任何重复的小数都不起作用(如.333333)。 用于堆栈溢出的所有其他函数都在Objective-C中。但我需要在我

  • 问题内容: 关于 Swift中的 时间转换,我有一个(有点?)基本问题。 我有一个整数,希望将其转换为小时/分钟/秒。 示例: 会给我: 我知道如何在PHP中执行此操作,但是可惜,Swift不是PHP :-) 我如何迅速实现这一目标的任何技巧都太棒了!先感谢您! 问题答案: 定义 用 要么 上面的函数利用Swift元组一次返回三个值。您可以使用语法对元组进行解构,或者可以根据需要访问单个元组成员。

  • 问题内容: 我需要将小数转换为分数。转换成10英尺很容易。 这可以通过以下代码完成: 但是我想要的是 而且我不知道如何进行。我的问题不是重复。因为其他相关问题是C#。这是java。 问题答案: 您应该找到结果数的最大公约数,然后除以分子和分母。 这是一种实现方法:

  • 这是我目前得到的 它告诉我小数点后有6位,因为它把“000”放在末尾。 我怎么解决这个? 尼克拉斯

  • 问题内容: 我正在尝试快速分隔双精度数的十进制和整数部分。我尝试了多种方法,但是它们都遇到了相同的问题… 有没有一种方法可以获取0.5678而不是0.567800000000034,而无需将数字转换为字符串? 问题答案: 无需将其转换为字符串,您可以将舍入到小数点后的位数,如下所示: 您的输出将是 0.5678

  • 本文向大家介绍JS小数转换为整数的方法分析,包括了JS小数转换为整数的方法分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JS小数转换为整数的方法。分享给大家供大家参考,具体如下: 一、小数转为整数 floor:下退 Math.floor(12.9999) = 12 ceil:上进 Math.ceil(12.1) = 13; round: 四舍五入 Math.round(12.5) =