Swift 中 Double 的拆分和合并
Splitting and combining of Double in Swift
我想将持续时间存储在 Double
中,并且需要提取 Double
(小时和分钟)的高值和低值以访问它们。我还需要能够使用两个 Ints
(hour
和 minute
)设置 Double
。
现在我在这里得到了一些东西:
extension Double {
func hour() -> Int {
return NSNumber(double: floor(self)).integerValue
}
func minute() -> Int {
return NSNumber(float: Float(Double((self - floor(self)) * 100))).integerValue
}
init(hour: Int, minute: Int) {
self = Double(hour) + ( Double(minute) / 100 )
}
}
然后我在我的 appDelegate 的 didFinishLaunchingWithOptions
:
中对此进行了一些测试
var time: Double = 18.30
NSLog("Time is \"%f\" - so hours is \"%d\" and minutes is \"%d\".", time, time.hour(), time.minute())
time = Double(hour: 10, minute: 1)
NSLog("Time is \"%f\" - so hours is \"%d\" and minutes is \"%d\".", time, time.hour(), time.minute())
time = Double(hour: 15, minute: 45)
NSLog("Time is \"%f\" - so hours is \"%d\" and minutes is \"%d\".", time, time.hour(), time.minute())
现在,此代码有效。有人可能想知道为什么我在 minute()
函数中将 Double
转换为 Float
。这是因为在将这些 Float
转换为 Int
之前,我在使用 Double
时未将它们转换为 Float
时遇到了一个未知问题。如果分钟未以 0
结尾,则由于未知原因减去一分钟。
例如,10:42 返回 10 小时 和 41 分钟.
但是 10:30 仍然是 10 小时和30分钟。
另外10:00是10小时和0分钟.
我在这里发布的这个例程似乎有效,但我只是想知道,如果我尽可能高效......这里的转换比需要的更多。
所以,任何改进?
有人知道我提到的分钟减少的未知问题的原因吗?
二进制浮点数如Double
或Float
不能准确表示数10.42
,因此
将小数部分乘以 100 并截断结果可能会得到 41
。
转换为 Float
你只是 "hiding" 问题所在。
这是一个 rounds 而不是截断的版本,总体上更简单一些。我从你的代码中采用了 "minute" 的符号,
即使它代表一小时的 1/100 而不是 1/60。
extension Double {
func hour() -> Int {
return Int(self)
}
func minute() -> Int {
return Int(round(self * 100.0)) % 100
}
init(hour: Int, minute: Int) {
self = Double(hour) + ( Double(minute) / 100 )
}
}
解决您的问题的其他可能方法:
将持续时间存储为 整数,代表总计
分钟数。例如。 “10:42”将存储为 10*60 + 42
。
那你就完全没有四舍五入的问题了。
使用基金会
输入 NSDecimalNumber
而不是 Double
,它可以表示
最多 38 位的十进制整数。
我想将持续时间存储在 Double
中,并且需要提取 Double
(小时和分钟)的高值和低值以访问它们。我还需要能够使用两个 Ints
(hour
和 minute
)设置 Double
。
现在我在这里得到了一些东西:
extension Double {
func hour() -> Int {
return NSNumber(double: floor(self)).integerValue
}
func minute() -> Int {
return NSNumber(float: Float(Double((self - floor(self)) * 100))).integerValue
}
init(hour: Int, minute: Int) {
self = Double(hour) + ( Double(minute) / 100 )
}
}
然后我在我的 appDelegate 的 didFinishLaunchingWithOptions
:
var time: Double = 18.30
NSLog("Time is \"%f\" - so hours is \"%d\" and minutes is \"%d\".", time, time.hour(), time.minute())
time = Double(hour: 10, minute: 1)
NSLog("Time is \"%f\" - so hours is \"%d\" and minutes is \"%d\".", time, time.hour(), time.minute())
time = Double(hour: 15, minute: 45)
NSLog("Time is \"%f\" - so hours is \"%d\" and minutes is \"%d\".", time, time.hour(), time.minute())
现在,此代码有效。有人可能想知道为什么我在 minute()
函数中将 Double
转换为 Float
。这是因为在将这些 Float
转换为 Int
之前,我在使用 Double
时未将它们转换为 Float
时遇到了一个未知问题。如果分钟未以 0
结尾,则由于未知原因减去一分钟。
例如,10:42 返回 10 小时 和 41 分钟.
但是 10:30 仍然是 10 小时和30分钟。
另外10:00是10小时和0分钟.
我在这里发布的这个例程似乎有效,但我只是想知道,如果我尽可能高效......这里的转换比需要的更多。
所以,任何改进?
有人知道我提到的分钟减少的未知问题的原因吗?
二进制浮点数如Double
或Float
不能准确表示数10.42
,因此
将小数部分乘以 100 并截断结果可能会得到 41
。
转换为 Float
你只是 "hiding" 问题所在。
这是一个 rounds 而不是截断的版本,总体上更简单一些。我从你的代码中采用了 "minute" 的符号, 即使它代表一小时的 1/100 而不是 1/60。
extension Double {
func hour() -> Int {
return Int(self)
}
func minute() -> Int {
return Int(round(self * 100.0)) % 100
}
init(hour: Int, minute: Int) {
self = Double(hour) + ( Double(minute) / 100 )
}
}
解决您的问题的其他可能方法:
将持续时间存储为 整数,代表总计 分钟数。例如。 “10:42”将存储为
10*60 + 42
。 那你就完全没有四舍五入的问题了。使用基金会 输入
NSDecimalNumber
而不是Double
,它可以表示 最多 38 位的十进制整数。