在Swift中获取双精度的小数部分
我试图在swift中分离双精度的小数部分和整数部分。我尝试了很多方法,但都遇到了相同的问题在Swift中获取双精度的小数部分,swift,math,floating-accuracy,Swift,Math,Floating Accuracy,我试图在swift中分离双精度的小数部分和整数部分。我尝试了很多方法,但都遇到了相同的问题 let x:Double = 1234.5678 let n1:Double = x % 1.0 // n1 = 0.567800000000034 let n2:Double = x - 1234.0 // same result let n3:Double = modf(x, &integer) // same result 有没有一种方法可以在不将数字转换
let x:Double = 1234.5678
let n1:Double = x % 1.0 // n1 = 0.567800000000034
let n2:Double = x - 1234.0 // same result
let n3:Double = modf(x, &integer) // same result
有没有一种方法可以在不将数字转换为字符串的情况下获得0.5678而不是0.56780000000034?使用
Float
,因为它的精度比Double
let x:Double = 1234.5678
let n1:Float = Float(x % 1) // n1 = 0.5678
在不将其转换为字符串的情况下,您可以将其四舍五入到小数位数,如下所示:
let x:Double = 1234.5678
let numberOfPlaces:Double = 4.0
let powerOfTen:Double = pow(10.0, numberOfPlaces)
let targetedDecimalPlaces:Double = round((x % 1.0) * powerOfTen) / powerOfTen
let d: Double = 1.23456e12
let intparttruncated = trunc(d)
let intpartroundlower = Int(d)
let d: Double = 1.23456e78
let exponent = trunc(log(d) / log(10.0))
let mantissa = d / pow(10, trunc(log(d) / log(10.0)))
您的输出将是
0.5678
Swift 2: 您可以使用:
modf(x).1
或
您可以使用
截断余数
和1
作为分隔符
使用截断除法返回此值的剩余部分除以给定值
例如:
let myDouble1: Double = 12.25
let myDouble2: Double = 12.5
let myDouble3: Double = 12.75
let remainder1 = myDouble1.truncatingRemainder(dividingBy: 1)
let remainder2 = myDouble2.truncatingRemainder(dividingBy: 1)
let remainder3 = myDouble3.truncatingRemainder(dividingBy: 1)
remainder1 -> 0.25
remainder2 -> 0.5
remainder3 -> 0.75
与Alessandro Ornano作为浮点协议实例属性实现的方法相同: Xcode 11•Swift 5.1
import Foundation
extension FloatingPoint {
var whole: Self { modf(self).0 }
var fraction: Self { modf(self).1 }
}
let x:Double = 1234.5678
let decimalPart:Double = x.truncatingRemainder(dividingBy: 1) //0.5678
let integerPart:Double = x.rounded(.towardZero) //1234
如果需要小数位数并保留其精度位数,则需要使用Swift
Decimal
键入并使用字符串对其进行初始化:
extension Decimal {
func rounded(_ roundingMode: NSDecimalNumber.RoundingMode = .bankers) -> Decimal {
var result = Decimal()
var number = self
NSDecimalRound(&result, &number, 0, roundingMode)
return result
}
var whole: Decimal { self < 0 ? rounded(.up) : rounded(.down) }
var fraction: Decimal { self - whole }
}
可以得到如下所示的整数部分:
let x:Double = 1234.5678
let numberOfPlaces:Double = 4.0
let powerOfTen:Double = pow(10.0, numberOfPlaces)
let targetedDecimalPlaces:Double = round((x % 1.0) * powerOfTen) / powerOfTen
let d: Double = 1.23456e12
let intparttruncated = trunc(d)
let intpartroundlower = Int(d)
let d: Double = 1.23456e78
let exponent = trunc(log(d) / log(10.0))
let mantissa = d / pow(10, trunc(log(d) / log(10.0)))
trunc()函数将截断小数点后的零件,Int()函数将舍入下一个较低的值。这对于正数是相同的,但是对于负数是不同的。如果你从d中减去被截断的部分,那么你将得到分数部分
func frac (_ v: Double) -> Double
{
return (v - trunc(v))
}
可以得到双精度值的尾数和指数,如下所示:
let x:Double = 1234.5678
let numberOfPlaces:Double = 4.0
let powerOfTen:Double = pow(10.0, numberOfPlaces)
let targetedDecimalPlaces:Double = round((x % 1.0) * powerOfTen) / powerOfTen
let d: Double = 1.23456e12
let intparttruncated = trunc(d)
let intpartroundlower = Int(d)
let d: Double = 1.23456e78
let exponent = trunc(log(d) / log(10.0))
let mantissa = d / pow(10, trunc(log(d) / log(10.0)))
指数的结果为78,尾数的结果为1.23456
希望这对您有所帮助。C的数学库中有一个函数,包括Swift在内的许多编程语言都允许您访问它。它被称为modf,在Swift中,它是这样工作的
//modf返回一个2元素元组
//第一个元素中有整数部分
//第二个元素的分数部分
让splitPi=modf(3.141592)
splitPi.0//3.0
splitPi.1//0.141592
您可以创建如下所示的扩展
extension Double {
func getWholeNumber() -> Double {
return modf(self).0
}
func getFractionNumber() -> Double {
return modf(self).1
}
}
Swift 5.1
import Foundation
extension FloatingPoint {
var whole: Self { modf(self).0 }
var fraction: Self { modf(self).1 }
}
let x:Double = 1234.5678
let decimalPart:Double = x.truncatingRemainder(dividingBy: 1) //0.5678
let integerPart:Double = x.rounded(.towardZero) //1234
这两种方法都返回双精度值
如果您想要一个整数作为整数部分,您可以使用
Int(x)
不可能创建一个适用于所有双精度
的解决方案。如果其他的答案曾经奏效,我也相信这是不可能的,它们不再奏效了
让_5678=1234.5678.description.drop{$0!=“}.description/.5678”
双精度(_5678)//0.5678
让_567=1234.567.description.drop{$0!=“}.description/.567”
双精度(_567)//0.566999999999
这似乎解决了双精度问题
用法:
print(34.46979988898988.decimal) // outputs 0.46979988898988
print(34.46.decimal) // outputs 0.46
对于被否决的人,你能指出你认为这是错误答案的任何原因吗?通过转换为浮动,你只是在毫无益处地抛出更多信息:这将给出一个不太准确的答案(0.567799985408782958984375
,而不是0.567800000000338332029059930450439453125
)@MarkDickinson这难道不是OP想要实现的吗?什么,一个离0.5678
更远的值?我怀疑。看这个:谢谢你的回答。这很好,但不幸的是,它对我不起作用,因为我事先不知道代码中的适当位数。我想我必须通过字符串转换:-/simple和preciselet d:Double=12.2让rem=d.truncingRequires(dividingBy:1)//0。1999999999999993@protspace0.199999999993
与0.20
相同。您只需要在向用户显示时使用NumberFormatter。如果需要更高的精度,可以使用Decimal
和字符串初始化器@LeoDabus谢谢,但是如果我以后在逻辑中需要这个0.2呢?“你怎么处理这件事?”很抱歉回复晚了。同样,如果您需要更高的精度,可以使用Decimal
它在1234.567
上不起作用。我相应地修改了答案。有没有办法将其转换回双精度?@ScottyBlades(十进制为NSDecimalNumber)。双精度值也会产生与截断余数相同的精度问题。例如,print(modf(35.46).1)
outputs0.46000000000000085
,这可能会破坏可平衡和可比较的方法,有时会翻转符号,在某些边缘情况下会根据您的逻辑除以零。