我的C代码中出现了奇怪的事情。
我想比较数字,我要四舍五入到小数点后4位。
我已经调试过,可以看到传入的数据。
tmp_ptr->current_longitude
的值为6722.31500000,tmp_ptr->current_latitude
的值为930.0876500000。
使用sprintf语句后:
charTmpPtrXPos = "6722.3150" and charTmpPtrYPos = "930.0876".
我希望speed_info-> myXPos和speed_info-> myYPos的结果完全相同,但奇怪的是speed_info->myXPos = 6722.31500000
和speed_info->myYPos > = 30.0876500000
的值,sprintf语句
charSpeedPtrYPos= "930.0877"
因此,基本上sprintf语句对第二个值的行为有所不同,并且似乎将其四舍五入。调试完之后,我知道sprintf语句的输入完全相同。
有人能想到这个的原因吗?
sizeOfSpeedList = op_prg_list_size (global_speed_trajectory);
tmp_ptr= (WsqT_Location_Message*)op_prg_mem_alloc(sizeof(WsqT_Location_Message));
tmp_ptr = mbls_convert_lat_long_to_xy (own_node_objid);
sprintf(charTmpPtrXPos, "%0.4lf", tmp_ptr->current_longitude);
sprintf(charTmpPtrYPos, "%0.4lf", tmp_ptr->current_latitude);
speed_info = (SpeedInformation *) op_prg_mem_alloc (sizeof (SpeedInformation));
for (count=0; count<sizeOfSpeedList; count++)
{
speed_info = (SpeedInformation*) op_prg_list_access (global_speed_trajectory, count);
sprintf(charSpeedPtrXPos, "%0.4lf", speed_info->myXPos);
sprintf(charSpeedPtrYPos, "%0.4lf", speed_info->myYPos);
//if((tmp_ptr->current_longitude == speed_info->myXPos) && (tmp_ptr->current_latitude == speed_info->myYPos))
if ((strcmp(charTmpPtrXPos, charSpeedPtrXPos) == 0) && (strcmp(charTmpPtrYPos, charSpeedPtrYPos) == 0))
{
my_speed = speed_info->speed;
break;
}
}
答案 0 :(得分:4)
printf()
通常舍入到最接近的十进制表示,并将绑定发送到“偶数”(即最后一位为0,2,4,6或8的表示)。
但是,您必须了解大多数在十进制中有限表示的数字在二进制浮点中无法有限表示。例如,实数930.08765
不能表示为二进制浮点数。你真正拥有的double
值(以及转换为十进制的值)是另一个数字,可能略高于930.08765
,很可能是930.0876500000000532963895238935947418212890625
。将此数字四舍五入到十进制表示930.0877
是正常的,因为它更接近此表示而不是930.0876
。
请注意,如果您使用的是Visual Studio,则* printf()函数可能会限制为显示17位有效数字,从而使您无法观察double
最近930.08765
的确切值。
答案 1 :(得分:2)
这是float
和double
之间的差异。
OP可能会将tmp_ptr->current_latitude
用作float
而将speed_info->myYPos
用作double
。除非空格/速度强制使用double
,否则建议OP使用float
。
int main() {
float f1 = 930.08765;
double d1 = 930.08765;
printf("float %0.4f\ndouble %0.4f\n", f1, d1);
return 0;
}
float 930.0876
double 930.0877
由于典型的float
使用IEEE 4字节二进制浮点表示,f1
采用的确切值为
930.087646484375
930.0876(这是4位数的打印结果)
这是与930.08765最接近的float
值。
同样地,对于double
,d1
具有确切的值
930.0876500000000532963895238935947418212890625
930.0877(这是4位数的打印结果)
一般来说,一个可以使用更多小数位来减少其他数字发生这种情况的可能性,但不消除它。
候选人快速解决方案
sprintf(charSpeedPtrYPos, "%0.4lf", (float) speed_info->myYPos);
这会首先将值从speed_info->myYPos
转换为float
。由于float
类型的非原型参数在传递给double
之前会转换为sprintf()
,因此该值将转换回double
。最终结果是数字精度损失,但字符串转换结果相同。
printf("(float) double %0.4f\n", (float) d1);
// (float) double 930.0876
BTW:l
中的"%0.4lf"
没有代码生成目的。但是允许这样做。
答案 2 :(得分:0)
请参阅:http://www.cplusplus.com/reference/cstdio/printf/
后跟数字的点指定精度,在您的情况下为4。如果需要,尽量使用更高的预定值。我已经尝试过你的数字,精度为5,它不再被四舍五入。所以它应该是......
sprintf(charSpeedPtrYPos, "%0.5lf", speed_info->myYPos);
..或任何符合您需求的更高数字。