将十进制时间转换为正常时间的功能无法正常工作

问题描述 投票:0回答:2

我有以下Python函数可以将正常时间转换为十进制时间,反之亦然:

import math

def std_to_dec(hour, minute, second):
    dec_total_seconds = (3600*hour+60*minute+second)/0.864
    dec_hour = int(str(dec_total_seconds/float(10000))[0])
    dec_minute = int(str(dec_total_seconds/float(10000))[2:4])
    dec_second = int(str(dec_total_seconds/float(10000))[4:6])
    return [dec_hour, dec_minute, dec_second]

def dec_to_std(hour, minute, second):
    std_total_seconds = (10000*hour+100*minute+second)*0.864
    std_hour = math.floor(std_total_seconds/float(3600))
    std_minute = math.floor((float(str(std_total_seconds/float(3600))[str(std_total_seconds/float(3600)).find('.'):]))*60)
    std_minute_dec = (float(str(std_total_seconds/float(3600))[str(std_total_seconds/float(3600)).find('.'):]))*60
    std_second = math.floor((float(str(std_minute_dec)[str(std_minute_dec).find('.'):]))*60)
    return [std_hour, std_minute, std_second]

当我这样做时

print(std_to_dec(18, 21, 47))
我得到
[7, 65, 12]
,这一切都很好。但当我尝试反之亦然时,
print(dec_to_std(7, 65, 12))
,我得到
[18, 21, 46]
,这是不一样的。

此外,

std_to_dec(0, 0, 0)
返回错误:

dec_second = int(str(dec_total_seconds/float(10000))[4:6]) ValueError: 以 10 为基数的 int() 的文字无效:''

dec_to_std(0, 0, 0)
虽然有效。

python time rounding
2个回答
0
投票

将标准时间转换为十进制时间(反之亦然)将导致某些值出现舍入错误。

在原来的问题中,OP 正在与字符串进行转换,这是完全没有必要的。如果我们采用数学方法,问题就会变得更清楚。

def std_to_dec(hh, mm, ss):
    seconds = int((((hh * 60) + mm) * 60 + ss) / 0.864)
    ds = seconds % 100
    seconds //= 100
    dm = seconds % 100
    return seconds // 100, dm, ds

def dec_to_std(hh, mm, ss):
    seconds = int((((hh * 100) + mm) * 100 + ss) * 0.864)
    ss = seconds % 60
    seconds //= 60
    sm = seconds % 60
    return seconds // 60, sm, ss

standard = 18, 21, 47
print('Standard time', standard)
sd = std_to_dec(*standard)
print('Decimal time', sd)
print('Recalculated', dec_to_std(*sd))

输出:

Standard time (18, 21, 47)
Decimal time (7, 65, 12)
Recalculated (18, 21, 46)

0
投票

通过使用字符串表示形式,您的代码期望有一个至少包含 6 个字符的字符串(情况并非总是如此),并忽略从第 7 个字符开始的任何字符,从而丢失精度,并导致转换回来时出现差异。

然而,一个核心问题是标准时间有 60*60*24 = 86400 种可能的次数,而小数时间有 10*100*100 = 100000(更多)可能的次数。因此,不可能存在一对一的映射,因为这样双方都需要相同数量的可能性。但是,由于标准时间的可能性较小,因此必须可以根据需要进行映射,但这意味着小数时间的某些可能性不会发生。

在将其转换为十进制时间并返回时,您可以使用以下方法始终获得相同的标准时间:

def std_to_dec(hour, minute, second):
    dec = round((3600*hour+60*minute+second)/0.864)
    dec_second = dec % 100
    dec //= 100
    dec_minute = dec % 100
    dec //= 100
    dec_hour = dec
    return [dec_hour, dec_minute, dec_second]

def dec_to_std(hour, minute, second):
    std = round((10000*hour+100*minute+second)*0.864)
    std_second = std % 60
    std //= 60
    std_minute = std % 60
    std //= 60
    std_hour = std
    return [std_hour, std_minute, std_second]

使用此解决方案,不可能期望相反的结果:存在小数时间,因此如果您将它们转换为标准时间并返回,它们不会产生相同的小数时间。同样,这是因为小数时间比标准时间多(当然仅使用整数时)。

例如:

std_to_dec(0, 0, 3) == [0, 0, 3]
std_to_dec(0, 0, 4) == [0, 0, 5]

这意味着小数时间 [0, 0, 4] 不会出现,也意味着如果从该小数时间开始进行逆向操作,则无法取回它:

dec_to_std(0, 0, 4) == [0, 0, 3]
© www.soinside.com 2019 - 2024. All rights reserved.