除法和浮点数

6

有人能帮我解释为什么x2输出为0吗?我猜是因为浮点数表示方式对X1进行了舍入,是否有方法可以保留精度。

long double x1, x2;
x1= 0.087912088; // Note: 360/4095 = 0.087912088
x2 = 360/4095;
printf("%Lf, %Lf \n",x1, x2);

结果:

x1 =0.087912
x2= 0.000000

Chris和Levon,谢谢你们的回复。有没有办法提高精度? - katta
要实际存储更多数字,您需要一个任意精度库。只显示更多可以像Levon所说的那样完成,或者在C++中使用std::setprecision - chris
@chris 我正在编写基于C语言的低级电机控制代码,运行在QNX嵌入式系统上。我会记住这点,以备将来编写C++代码时使用。 - katta
为了让其他人在未来更容易理解,考虑这两个词典条目:precessionprecision - Alexey Frunze
可能是重复的问题:我的浮点运算出了问题 - juanchopanza
2个回答

10
问题是“整数截断”...你正在除以两个整数=>结果将成为另一个整数,小数部分被丢弃。 (因此,例如在整数除法的情况下,如果实际结果是3.9,则截断会使其变为3(即不四舍五入))。
在您的情况下,如果您将其更改为:
x2 = 360 / 4095.0;  /* one of the operands now has a decimal point */

你将会得到什么

0.087912, 0.087912 
作为输出结果。
即,只要除法运算符的一个或两个操作数是float/double类型,结果也将是float/double类型(即它将被“提升”为float/double类型)。因此,我可以将x2更改为。
x2 = 360.0 / 4095.0;
或者
x2 = 360.0 / 4095;

并且会得到与上面相同的结果。

正如@chris所提到的,仅使用一个.也足够了。

关于精度,针对你之前的问题:

你已经在使用长双精度浮点数了……我认为在不使用特殊库的情况下内部不能改变任何东西,但你可以显示更多位数。例如,

  printf("%Lf, %.20Lf \n",x1, x2); 

将产生

  0.087912, 0.08791208791208791895 

最后,正如@edA-qa mort-ora-y提醒我们的那样,您也可以将值强制转换为特定类型,但是它很重要,何时这样做。以下是一个简单的例子(请注意,由于vfloat,因此无论如何赋值之后,值最终都会成为float):

float v = 0;
                     /* values shown are BEFORE assignment */
v = (5 / 2);         /* value is 2 due to integer truncation before assignment */
v = (float) (5 / 2); /* 2.0 as integer division occurs 1st, then cast to float */
v = (float) 5 / 2;   /* 2.5 since 5 becomes 5.0 through casting first. */

只需要在末尾加一个点就可以了。 - chris
@chris 谢谢..我没有意识到..学到了新东西 :) 我会把这个加入答案中。 - Levon
您还可以转换为浮点数,这在需要提升变量而不是常量时非常有用。float(a)double(4) - edA-qa mort-ora-y
@edA-qamort-ora-y 的观点很好,谢谢提醒,我会在答案中添加有关强制类型转换的注释。 - Levon

3
内置的运算符适用于相同类型的对象。结果与参数的类型相同。在本例中,除法是在两个整数之间进行的,因此结果也是整数。
x2 = 360/4096;
//   int/int  = int

因此,我预期结果为0。

如果内置类型的运算符不同,则会提升其中一个以使它们具有相同的类型(并且结果也是该类型)。所以你想要的是:

x2 = 1.0 * 360/4095;  // or 360.0/4095

// This is
    double * int / int

==> (double * double)/int
==> (double * double)/double

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接