为什么在循环中具有浮点的数字的乘法不像其外部那样精确?
我正在编写一个程序来计算用
,使用泰勒系列,其中包括提高其中的某些特定权力的术语。由于我是C的新手,因此我决定仅以练习来编写自己的x
在[0,1]
中计算pow()
功能。但是后来我注意到我的程序无法正确计算正弦功能。在检查时,我发现在循环中提高一个数字并没有产生与简单直接乘法相同的结果... v * v * v ...
这是我的powr()
功能和结果的差异:
#include <stdio.h>
double powr(double base, int power)
{
if (power == 0) {
base = 1;
} else if (power > 0) {
for (int i = 1; i < power; i++) {
base *= base;
}
} else {
// power is negative.
}
printf("In loop number to a power of 3: %lf\n", base);
double hard_coded = 0.99 * 0.99 * 0.99;
printf("Out of loop number to a power of 3: %lf\n", hard_coded);
return base;
}
int main(void)
{
double num = 0.99;
double num_to_power = powr(num, 3);
return 0;
}
输出:
In loop number to a power of 3: 0.960596
Out of loop number to a power of 3: 0.970299
0.960596和0.970299看起来并不不同,但是较小的值误差变得更大。 为什么要解决问题?
也,我只是注意到,如果我采用0.123
之类的小价值,并将它们提高到6 ,例如。我有一个输出,例如
0.000000
。我知道它太小了,无法出现。但是,如何打印一个超过6个点数的浮点数?我尝试了长double
,也没有起作用。
I was writing a program to calculate sin(x)
with x
in [0, 1]
, using Taylor series that include raising some of its terms to a certain power. Since I'm new to C, I decided to write my own pow()
function just to practice. But then I noticed that my program doesn't calculate the sine function correctly. Upon an examination, I discovered that raising a number to a power in a loop doesn't produce the same result as simple straightforward multiplication ...v * v * v...
Here's my powr()
function and difference in results:
#include <stdio.h>
double powr(double base, int power)
{
if (power == 0) {
base = 1;
} else if (power > 0) {
for (int i = 1; i < power; i++) {
base *= base;
}
} else {
// power is negative.
}
printf("In loop number to a power of 3: %lf\n", base);
double hard_coded = 0.99 * 0.99 * 0.99;
printf("Out of loop number to a power of 3: %lf\n", hard_coded);
return base;
}
int main(void)
{
double num = 0.99;
double num_to_power = powr(num, 3);
return 0;
}
Output:
In loop number to a power of 3: 0.960596
Out of loop number to a power of 3: 0.970299
0.960596 and 0.970299 may not look that different, but with smaller values an error becomes even bigger.
Why is that and how can I solve it?
Also, I just noticed that if I take small values like 0.123
and raise them to a power of 6
, for example. I have an output like 0.000000
. I understand that it's just too small to show up. But how can I print an a floating-point number that has more than 6 after point numbers? I've tries long double
, didn't work either.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的循环计算是错误的。
base *= base;
线将在每个循环上,将“累计”值乘以修改的值在上一个循环上,而不是通过< em>原始 value(应该)。您需要存储传递的
base
值,并将保存值作为每个循环上的乘数使用:两个输出阀将是等效的:
Your loop calculation is wrong. The
base *= base;
line will, on each loop, multiply the 'accumulated' value by the value that has been modified on the previous loop, rather than by the original value (as it should).You need to store the passed
base
value and use that saved value as the multiplier on each loop:The two output vales will then be equivalent:
首先,您的循环不会计算所需的内容:
在您的情况下,您正在计算:
base *= base
将给出base = 0.99 *0.99 = 0.9801
base = 0.9801 *09801 = 0.96059601
通过累积先前的结果,随着时间的流逝,您正在计算
base^(2^(exp-1)<(exp-1)< /代码>。那就不足为奇了。为了进行启动,这样的简单循环将使它成为:
如果您想更快地使其使用平方,则存在一个简单的快速凸起( https://en.wikipedia.org/wiki/exponention_by_squaring )。
其次,硬编码版本可以由编译器以任何其他方式计算,并且由于浮点计算对于四舍五入的错误非常明智,因此结果可能是不同的。
First, your loop does not calculate what you need:
In you case you are calculating:
base *= base
will givebase=0.99*0.99=0.9801
base *= base
will givebase=0.9801*09801=0.96059601
By accumulating previous result over time you are calculating
base^(2^(exp-1))
. No surprise then. For exponentiation a simple loop like this will make it:There exists a simple fast exponentiation that use squaring if you want to make it faster (https://en.wikipedia.org/wiki/Exponentiation_by_squaring).
Second, the hard coded version can be computed by the compiler in any other way, and as floating point computation is very sensible to rounding errors, the result may be different.