3

我用 c 编写物理(蒙特卡罗自旋磁场)模拟,遇到了一种奇怪的问题。if 语句仅适用于一个变量的某个值。我想做的是我有一个具有一定初始值的变量(bh,外部磁场)。我继续减少它,直到它在 10 步内达到 -bh,然后它应该开始增加,直到它再次达到 +bh,依此类推,直到迭代结束。这适用于 bh=.3,但如果我将其设置为 .1、.2 或 1,则它不起作用。它开始减少,但直到模拟结束才停止。我的程序中没有其他值等于 0.3!

我不确定要包括什么,因为主程序有点长。但代码片段是(没有主循环,但包括调试回声):

 float bh;  float bmax;
 bh=.3; bmax=bh;

if (bup==1) {
     printf("BUP=1, BFeld = %.2f\n",bh);
     bh = bh + bmax/10;
     if (bh == bmax) { bup=0; }
}
if (bup==0) {
    printf("BUP=0, BFeld = %.2f, %.2f = bmin\n",bh,-bmax);
    bh = bh - bmax/10;
    if (bh == -bmax) { bup=1; }
}

我在调试输出方面得到的是 bh=.3

[...]
BUP=0, BFeld = -0.24, -0.30 = bmin
BUP=0, BFeld = -0.27, -0.30 = bmin
BUP=1, BFeld = -0.30
BUP=1, BFeld = -0.27
BUP=1, BFeld = -0.24
[...]

但是当我将 bh 设置为 1 时,我得到

[...]
BUP=0, BFeld = -0.80, -1.00 = bmin
BUP=0, BFeld = -0.90, -1.00 = bmin
BUP=0, BFeld = -1.00, -1.00 = bmin
BUP=0, BFeld = -1.10, -1.00 = bmin
BUP=0, BFeld = -1.20, -1.00 = bmin
BUP=0, BFeld = -1.30, -1.00 = bmin
[...]

所以我的调试输出甚至给了我“...-1.00,-1.00...”这一行,但不知何故,c 认为它们不等于“足够”将 bup 设置为 1。我做错了什么?

4

3 回答 3

4
if (bh == bmax) { bup=1; }

由于四舍五入==,用于比较浮点数的结果通常不是您所期望的。

定义EPSILON为一些合理的小值并比较浮点数,如下所示:

if (fabs(bh - bmax) < EPSILON)
于 2013-07-05T00:45:36.680 回答
3

您永远不应该使用浮点变量测试是否相等。您需要在一定的公差范围内进行测试。例如:

#define EPSILON (0.000001)
if (fabs(bh - bmax) < EPSILON)
于 2013-07-05T00:48:03.760 回答
0

正如其他人所说,您不应该比较浮点数,==因为该运算符会搜索精确匹配。

即使您的数字在以十进制表示法(±.3 和 ±.03 步长)表示时看起来很简单,但当转换为内部二进制表示 od FP 数字时,它们会导致无限重复位模式(类似于重复小数)。由于 FP 数字的大小有限,超出的位要么被截断,要么被舍入,但在任何一种情况下,它们的连续累积可能会增加,这可能会导致与预期数字的精确表示的偏差越来越大。

于 2013-07-05T01:09:44.920 回答