C语言中用float实现H.MMSS与十进制小时转换的问题排查
十进制小时与H.MMSS格式转换的float精度问题
我正在开发一组函数,用于在十进制小时(2小时30分钟为2.5小时)与H.MMSS格式(2.5小时表示为2.3000)之间进行转换。最初用double实现时一切正常,但嵌入式项目规模扩大后闪存不足,不得不改用float。
以下是复现问题的最小可执行示例(MWE):
#include <stdio.h> #include <math.h> float toHMS(float inputTime) { float hours = 0; float minutes = 0; float seconds = 0; // get integral part for the hours hours = (int)inputTime; // transform into decimal minutes inputTime -= hours; inputTime *= 60; // Get the minutes minutes = (int)inputTime; // Get the seconds inputTime -= minutes; seconds = (int)(100 * inputTime); return hours + minutes/100 + seconds/ 10000; } float toHours (float inputTime) { float hours = 0; float minutes = 0; float seconds = 0; // get integral part for the hours hours = (int)inputTime; inputTime = 100 * (inputTime - hours); minutes = (int)inputTime; inputTime = inputTime - minutes; seconds = 100 * inputTime; // normalize to 60 minutes = minutes / 60; seconds = seconds / 3600; return hours + minutes + seconds; } float toHours2 (float inputTime) { float hours = 0; float minutes = 0; float seconds = 0; // get integral part for the hours hours = (int)inputTime; inputTime = roundf(100 * (inputTime - hours)); minutes = (int)inputTime; inputTime = inputTime - minutes; seconds = 100 * inputTime; // normalize to 60 minutes = minutes / 60; seconds = seconds / 3600; return hours + minutes + seconds; } void main(void) { float hms = toHMS(2.5f); printf("toHMS(2.5f): %.9f\n", hms); printf("toHours(toHMS(2.5f)): %.9f\n", toHours(hms)); printf("\n"); printf("toHours(2.3f): %.9f\n", toHours(2.3f)); printf("\n"); printf("toHours2(2.3f): %.9f\n", toHours2(2.3f)); }
运行结果:
toHMS(2.5f): 2.299999952 toHours(toHMS(2.5f)): 2.511111021 toHours(2.3f): 2.511111021 toHours2(2.3f): 2.500000000
问题出在toHours()函数中,因为单精度float的2.3实际存储为2.299999952。在toHours2()中添加roundf()后问题得到解决,但不确定这是否是唯一所需的修复,是否存在其他输入会导致计算出错,无法证明该方案适用于所有情况。
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

