与atof的奇怪行为

Kev*_*vin 2 floating-point c-strings atof

我有一个Arduino从我的智能手机(通过蓝牙)接收包含unix时间戳的消息.现在,我正在尝试将DS1307与该时间戳同步.

但是,它没有用,因此,我开始搜索并在将包含时间戳的C风格数组转换为浮点数时发现了一些奇怪的行为.

// Copy the time into "timeBuff"
int timeLength = siz - _CAT_LENGTH_;
char timeBuff[timeLength+1];
memcpy(timeBuff, &msg[_CAT_LENGTH_], timeLength);
timeBuff[timeLength] = '\0';

// For debugging
Serial.print(F("timeBuff:   "));
Serial.println(timeBuff);

// Convert timeBuff string into a variable of type long
float deviceTime = atof(timeBuff);

// Now, deviceTime != what we printed above
Serial.print(F("Epoch time: "));
Serial.println(deviceTime);
Run Code Online (Sandbox Code Playgroud)

前5行将消息的右侧部分复制到字符数组中,并添加终止零.

然后,我们打印内容timeBuff并将其转换float为存储的内容deviceTime.最后,我们打印deviceTime.

这是我第一次测试的结果

timeBuff:   1476113620
Epoch time: 1476113664.00
Run Code Online (Sandbox Code Playgroud)

这是第二次测试

timeBuff:   1476115510
Epoch time: 1476115456.00
Run Code Online (Sandbox Code Playgroud)

为什么结果atof与我们传递的字符串不同?

AnT*_*AnT 5

在大多数平台float上用IEEE-754单精度格式表示,它是32位浮点格式,具有24位(23 + 1)有效位.它根本没有足够的精度来表示你的数字.您的数字需要大约32位才能表示.当存储时,大于24位的整数值通常会失去精度float.

精度的损失将表现为丢失尾随位,并在最后剩余的位中进行舍入

1476113620 -> ?01010111111110111011010011010100?
1476113664 -> ?01010111111110111011010100000000?
Run Code Online (Sandbox Code Playgroud)