我正在制作一个计算器,希望它能自动将每个小数转换成小数。因此,如果用户计算一个表达式,答案是“0.333333......”,它会返回“1/3”。对于“0.25”,它会返回“1/4”。使用GCD,如这里所示(小数到小数的转换),我已经知道如何将任何有理的、终止的小数转换成小数,但这对任何重复的小数都不起作用(如.333333)。
用于堆栈溢出的所有其他函数都在Objective-C中。但我需要在我的swift应用程序中使用一个函数!这是一个翻译版本(https://stackoverflow.com/a/13430237/5700898)太好了!
正如马丁·R所说,拥有(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
首先,我们有类本身。类可以用两种方式初始化:
在Rational类中,alpha~=提名者
第一种方法是使用两个整数初始化类,第一个是命名符,第二个是分母。该类获取这两个整数,然后将它们减少到尽可能少的数字。e、 g将(10,5)减少到(2,1),或者作为另一个例子,将(144,60)减少到(12,5)。这样,总是存储最简单的数字。使用gcd(最大公约数)函数和simplifier函数可以实现这一点,这在代码中并不难理解。唯一的一点是,这个类面临一些负数的问题,所以它总是保存最终的有理数是负数还是正数,如果它是负数,它会使提名者为负数。
初始化类的第二种方法是使用一个double和一个名为“accurity”的可选参数。该类获取双精度,以及小数点后所需数字的精度,并将双精度转换为命名符/分母形式,其中分母的幂为10。e、 G2.334将为2334/1000或342.57将为34257/100。然后尝试使用#1方法解释的相同方法简化有理数。
在类定义之后,有类型别名“Rnl”,您显然可以根据自己的意愿更改它。
然后有4个函数,对于数学的4个主要动作: * / -, 我定义了,例如,你可以很容易地乘以两个Rational类型的数字。
之后,Rational类型有2个扩展,其中第一个('value')给出Rational数字的双倍值,第二个('rnlValue')以人类可读的字符串形式给出Rational数字:"提名者/分母"
最后,你可以看到所有这些是如何工作的一些例子。
所以有点晚了,但我遇到了一个类似的问题,最终构建了Swift FractionFor事例。这很有效,因为你关心的大多数无理数都是庸俗或常见分数集的一部分,很容易验证正确的转换。其余的可能四舍五入,也可能不四舍五入,但你可以非常接近用户可能生成的任何合理分数。它被设计成数字形式的替代品。
如果要将计算结果显示为有理数,那么唯一100%正确的解决方案是在所有计算中使用有理算术,即所有中间值都存储为一对整数(分子、分母)
,以及所有加法、乘法、除法、,etc是使用有理数的规则来完成的。
一旦结果被分配给二进制浮点数,如Douple
,信息就会丢失。例如,
let x : Double = 7/10
存储在x
中的近似值为0.7
,因为该数字不能精确表示为双精度
。从…起
print(String(format:"%a", x)) // 0x1.6666666666666p-1
你可以看到,x
持有这个值
0x16666666666666 * 2^(-53) = 6305039478318694 / 9007199254740992
≈ 0.69999999999999995559107901499373838305
因此,x
作为有理数的正确表示应该是6305394748318694/9007199254740992
,但这当然不是你所期望的。你所期望的是7/10
,但还有另一个问题:
let x : Double = 69999999999999996/100000000000000000
将完全相同的值赋给x
,在双精度范围内,它与
0.7
无法区分。
那么,
x
应该显示为7/10
还是69999999996/1000000000000000
?
如上所述,使用有理算术将是完美的解决方案。如果这是不可行的,那么你可以将<代码>双
转换回给定精度的有理数。(以下摘自Swift中双打的LCM算法。)
连续分数是一种有效的方法来创建分数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)
默认精度为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)
}
例如:
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)
问题内容: 我正在构建一个计算器,并希望它自动将每个小数 转换为分数。因此,如果用户计算出答案 为“ 0.333333…” 的表达式,它将返回“ 1/3”。对于“ 0.25”,它将返回“ 1/4”。 使用GCD(小数到小数 转换),我已经弄清楚了如何将任何有理数,终止 小数转换为小数,但这不适用于任何重复的小数 (如.333333)。 堆栈溢出的所有其他功能在Objective-C中。但是我需要
问题内容: 我需要将小数转换为分数。转换成10英尺很容易。 这可以通过以下代码完成: 但是我想要的是 而且我不知道如何进行。我的问题不是重复。因为其他相关问题是C#。这是java。 问题答案: 您应该找到结果数的最大公约数,然后除以分子和分母。 这是一种实现方法:
我发现了这个美丽的小数到小数的函数:https://gist.github.com/natecook1000/9ecc976aaac9a035bddf 我已经操纵了我的应用程序的必要性,并希望在制作Kotlin版本的帮助上面。我确实尝试过自己进行转换,但我是一名新手,在科特林只呆了3周。我没有足够的经验来匹配不同语言之间的语法和语义,我自己也做不到。感谢您的帮助:) 我将上面的内容更改为输出16英
问题内容: 我有一个要读取数据的CSV文件,我想将其读入Python。我得到包含类似字符串的列表。现在这样做不起作用,因为它的小数点错误。 我如何将其读入Python ? 问题答案: 在大多数情况下会做 如果数量庞大且已使用了数千个,则可以: 将所有逗号替换为要点: 删除除最后一点以外的所有内容:
本文向大家介绍JS小数转换为整数的方法分析,包括了JS小数转换为整数的方法分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JS小数转换为整数的方法。分享给大家供大家参考,具体如下: 一、小数转为整数 floor:下退 Math.floor(12.9999) = 12 ceil:上进 Math.ceil(12.1) = 13; round: 四舍五入 Math.round(12.5) =
问题内容: 关于 Swift中的 时间转换,我有一个(有点?)基本问题。 我有一个整数,希望将其转换为小时/分钟/秒。 示例: 会给我: 我知道如何在PHP中执行此操作,但是可惜,Swift不是PHP :-) 我如何迅速实现这一目标的任何技巧都太棒了!先感谢您! 问题答案: 定义 用 要么 上面的函数利用Swift元组一次返回三个值。您可以使用语法对元组进行解构,或者可以根据需要访问单个元组成员。