有关浮点数精度的一个问题

2013-12-11 10:46:44 +08:00
 christianwong
如下php代码:

$f = 0.58;
print_r(intval($f*100));

输出57,


如下C语言代码:
#include <stdio.h>

int main()
{
float f = 0.58;

int a = f*100;

printf("%d\r\n", a);

return 0;
}

输出58.


这是系统问题,还是语言问题?
不同的语言对浮点数的策略还不一样?
3903 次点击
所在节点    PHP
18 条回复
bombless
2013-12-11 10:57:55 +08:00
因为一个是单精度浮点数一个是双精度浮点数。
你把C语言里那个float换成double,就可以看到输出还是57.
master
2013-12-11 11:03:26 +08:00
首先需要明白的是浮点数在计算机(二进制)中的存储方式的特殊性。
另外你用了类型转换,所以这个已经不算存储精度的问题,而是转换策略的问题
christianwong
2013-12-11 11:09:07 +08:00
@master 恩,应该是你说的这个,php不会做相应的优化,而gcc可以
oldcai
2013-12-11 11:10:22 +08:00
你%d当然是58,%f看看?
justfindu
2013-12-11 11:11:24 +08:00
christianwong
2013-12-11 11:11:27 +08:00
@bombless 确实换成double就会输出57,原来php中的浮点数都是双精度的
christianwong
2013-12-11 11:11:48 +08:00
@justfindu 确实是看过这个文章之后想起的一个问题
mille
2013-12-11 11:11:49 +08:00
只要把浮点值赋给整形变量,小数点后面的都会被删节
christianwong
2013-12-11 11:12:52 +08:00
@oldcai %f输出的竟然全是0
oldcai
2013-12-11 11:14:29 +08:00
float a = f*100;

printf("%f\r\n", a);
bombless
2013-12-11 11:17:51 +08:00
如果不是出于存储或者网络传输的目的,单精度浮点数根本没有什么用。
所以多数编程语言根本就没有单精度浮点数只有双精度浮点数。

不过在计算机图形这一块,内存到显存的传输消耗很高,存储也很宝贵,甚至有使用双字节长的浮点数的。
christianwong
2013-12-11 11:46:33 +08:00
@oldcai 仍然输出58
christianwong
2013-12-11 11:46:46 +08:00
@bombless 多谢,长见识了
oldcai
2013-12-11 13:03:13 +08:00
@christianwong 已测试,输出58.000000,你看看是不是哪里出问题了。
prove.c:

#include<stdio.h>

int main(void)
{
float f = 0.58;
float a = f*100;
printf("%f\r\n", a);
return 0;
}

gcc -Wall prove.c -o prove
jiji9081
2013-12-11 16:52:22 +08:00
我觉得是转换策略的问题。
单精度浮点数的精度大概是6~7位有效数字,对付这种情况绰绰有余。
float f = 0.58;
a = f*100.0;
得到结果是57
但是
float f = 0.58;
f = f * 100;
a = f;
结果是58

事实上,在float f = 0.58这里已经存在有误差,实际保存的值换算成10进制是0.5799999237060547
那么×100后得到的就是57.99999237....这样的
两种策略一种是扔掉小数点,一种是舍入为最接近值

@oldcai
jiji9081
2013-12-11 16:59:13 +08:00
@oldcai
我是在Labwindows测试的,工具比较小众呵呵
oldcai
2013-12-11 17:12:34 +08:00
你出现的情况实在是比较奇怪,我以为是你没有把int a改成float a
skydiver
2013-12-11 17:31:55 +08:00
所以一般都是用 $b = intval(round($a));

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/92674

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX