Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.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
在Swift中获取双精度的小数部分_Swift_Math_Floating Accuracy - Fatal编程技术网

在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 有没有一种方法可以在不将数字转换

我试图在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

有没有一种方法可以在不将数字转换为字符串的情况下获得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@protspace
0.199999999993
0.20
相同。您只需要在向用户显示时使用NumberFormatter。如果需要更高的精度,可以使用
Decimal
和字符串初始化器@LeoDabus谢谢,但是如果我以后在逻辑中需要这个0.2呢?“你怎么处理这件事?”很抱歉回复晚了。同样,如果您需要更高的精度,可以使用
Decimal
它在
1234.567
上不起作用。我相应地修改了答案。有没有办法将其转换回双精度?@ScottyBlades
(十进制为NSDecimalNumber)。双精度值也会产生与截断余数相同的精度问题。例如,
print(modf(35.46).1)
outputs
0.46000000000000085
,这可能会破坏可平衡和可比较的方法,有时会翻转符号,在某些边缘情况下会根据您的逻辑除以零。