我正在编写代码,其中需要从初始值中减去每半秒进行的测量,最终达到0。这两个值都是浮点数。初始值为1.4亿,测量范围为0.320000001至0.389999999。
float batt = 140000000.00; //capacity 140M units
float subtr;
/.../
while(1){
batt = float(batt - subtr);
/.../
}
所以基本上我需要从148,000,000.00的循环的每个周期中减去0.3xxxxxxxx,但是似乎存在大小问题,因此当我对其进行调试时,每次仍然可以获得148M。
我尝试使用小1000倍的batt
batt值148 000,并将测量值从0.3xxxxxxxx转换为0.0003xxxxxxxx。调试代码时,148000-0.000300005049(测量值)给我147999.469,与预期结果(147,999.999,699)相比差了0.530699。
float似乎不够准确,无法满足我的需要,我应该将值转换为其他类型,还是有其他方法可以获得准确的结果?正在考虑将度量转换为不带小数的值,但这也不起作用,因为初始值对于float(148 * 10 ^ 15)会变得太大。当我使用140,000,000.00时,我期望获得小数点后三位(.xxx)的精度;当我使用140,000.00时,期望获得六位小数点(.xxx,xxx)的精度。
答案 0 :(得分:5)
当您执行140000000-0.389时,第二个操作数需要缩放以具有与第一个相同的指数:1.4e8 - 0.00000000389e8 = 1.39999999611e8
。英特尔CPU当前以扩展精度80位格式进行浮点计算,但是当将结果存储回32位float
时1.39999999611e8
会四舍五入为1.4e8
,因为float
具有精度大约为6个十进制数字。
存储十进制数字148000000.0003xxxxxxxx大约需要24个十进制数字的精度或80个二进制数字。 80位的long double
可能会这样做:
int main() {
float a = 140000000.f;
float b = 0.389999999f;
printf("%f\n", a);
printf("%f\n", b);
printf("float result: %.16f\n", a - b); // Round the 80-bit extended precision result to 32-bit.
printf("double result: %.16f\n", static_cast<double>(a)); // Round the 80-bit extended precision result to 64-bit.
printf("long double result: %.16Lf\n", static_cast<long double>(a) - b); // 80-bit extended precision result.
}
输出:
140000000.000000
0.390000
float result: 140000000.0000000000000000
double result: 140000000.0000000000000000
long double result: 139999999.6100000143051147