小数小时显示4分60秒而不是5分钟

时间:2016-12-18 09:29:26

标签: swift

我认为标题说明了一切,但让我再谈谈它了。

当用户使用我的应用时,我每隔5分钟在数据库中存储十进制小时数。我在显示5分钟块的正确时间时遇到了一些麻烦,因为它显示4分60秒。每隔3分钟5分钟显示一次。

这样的事情

4:60
10:00
15:00
19:60

有些甚至有n:59而不是n:00

部分代码是:

let hours = Int(floor(decimalHour))
let mins = Int(floor(decimalHour * 60) % 60)
let secs = Int(floor(decimalHour * 3600) % 60)

有什么建议我可能做错了吗?

1 个答案:

答案 0 :(得分:3)

二进制浮点数不能代表所有数字 确切地说,因此您的代码容易出现舍入错误。 示例(Swift 2):

let decimalHour = 1.0 + 5.0/60.0

print(decimalHour.debugDescription) // 1.0833333333333333
print(floor(decimalHour * 3600)) // 3899.0

let hours = Int(floor(decimalHour))
let mins = Int(floor(decimalHour * 60) % 60)
let secs = Int(floor(decimalHour * 3600) % 60)

print(hours, mins, secs) // 1 5 59

decimalHour中存储的实际数字略小于1 + 5/60,因此错误地计算了秒数。

(另请注意,您不能将%与浮点数一起使用 在Swift 3中,比较What does "% is unavailable: Use truncatingRemainder instead" mean?。)

正如评论中所说,更好的方法是 将持续时间存储为整数(秒数)。

如果无法做到,浮点数编号为 a秒数然后继续使用纯整数 算术。示例(适用于Swift 2 + 3):

let decimalHour = 1.0 + 5.0/60.0

let totalSeconds = lrint(decimalHour * 3600) // round to seconds
let hours = totalSeconds / 3600
let mins = (totalSeconds % 3600) / 60
let secs = totalSeconds % 60

print(hours, mins, secs) // 1 5 0