【问题标题】:Error, cannot determine if this expression is true or false (Bisection method)错误,无法确定这个表达式是真还是假(二分法)
【发布时间】:2021-05-11 23:34:08
【问题描述】:

我正在为二分法编写代码,并且几乎在我使用的每一种方法中都会出现此错误。我似乎无法确定问题所在,我应该使用二分法、假法位置和割线法。每次我运行代码它都会给我这个错误代码

                                   -8
                          E := 1 10  

S := 0.1*10^(-7);
                                   -8
                          S := 1 10  

f := x -> 950*ln(200000/(200000 - 3000*x)) + (-1)*9.81*x - 500;
f := proc (x) options operator, arrow; 950*ln(200000/(200000-300\

  0*x))-9.81*x-500 end proc


a := 10;
                            a := 10

b := 50;
                            b := 50

while S <= b - a or E <= abs(f(a)) and E <= abs(f(b)) do
    p := (a + b)/2;
    if f(p) = 0 then
        break;
    elif f(a)*f(p) < 0 then
        b := p;
    else
        a := c;
    end if;
end do;
                            p := 30

Error, cannot determine if this expression is true or false: (950*ln(20/17)-598.10)*(950*ln(20/11)-794.30) < 0



【问题讨论】:

    标签: maple


    【解决方案1】:

    内部有条件检查,

    if ... then
    

    使用 Maple 的 evalb 进行测试。但是ab 的初始值是精确的,而不是浮点数,所以evalb 不是正确的检查。这就是该错误消息的含义,它无法仅使用默认的evalb 检查器(布尔测试)来判断该不等式是否成立。

    最直接的做法是通过调用evalf 将不等式两边的表达式(用于条件检查)包装起来。然后不质量检查的两边都会变成浮点数,常规的evalb 测试会起作用。这也处理了用户提供的函数 f 本身产生真实但精确值而不是浮点数的情况。

    另一种方法是在条件中的不等式周围使用is,但是如果您不强制使用任何evalf,那么p 的每次迭代可能会变成一个巨大的精确混乱.这不是你想要的。

    你至少犯了一个错误:你有a := c,你的意思是a := p

    我大致了解您想要什么样的停止标准,但它存在问题。因为 Maple 默认使用Digits=10 工作精度,所以b-a 不会变得小于E。并且对f(p)=0 的检查是准确且不充分的;它可能永远不会完全为零。例如,abs(f(p)) &lt; E 或您决定的任何容忍度可能更好。

    但您确实需要更严格的停止标准。正如所写,它将永远消失。由于固定的工作精度意味着您只能成功细分到 Digits 指定的特定浮点精度,因此您可以尝试以下方法之一。

    restart;
    E := 1e-8:
    f := x -> 950*ln(200000/(200000 - 3000*x)) + (-1)*9.81*x - 500:
    a := 10:
    b := 50:
    while evalf(f(a)*f(b)) < 0 and
          evalf(abs((b-a)/b)) >= 6*10^(-Digits) do
        p := evalf((a + b)/2);
        if abs(f(p)) < E then
            break;
        elif evalf(f(a)*f(p)) < 0 then
            b := p;
        else
            a := p;
        end if;
    end do;
    a, f(a), p, f(p), b, f(b);
    

    或者,比如说,

    restart;
    E := 1e-8:
    f := x -> 950*ln(200000/(200000 - 3000*x)) + (-1)*9.81*x - 500:
    a := 10:
    b := 50:
    p := evalf((a + b)/2):
    while evalf(f(a)*f(b)) < 0
          and (p-a) <> 0.0 and (b-p) <> 0.0 do
        if abs(f(p)) < E then
            break;
        elif evalf(f(a)*f(p)) < 0 then
            b := p;
        else
            a := p;
        end if;
        p := evalf((a + b)/2);
    end do;
    a, f(a), p, f(p), b, f(b);
    

    可以随意放回一些您自己的停止标准,但要小心括号。并且您需要对p = evalf((a+b)/2)ab 进行相同的计算——请参阅我的两个替代方案,以防止由于这种浮点责任而导致的失控循环。

    更好的是,添加一个循环计数器并在允许的最大迭代次数处停止。你可以让它变大。由于代码错误和缺乏防御性编程而永远消失的循环有点难看。

    此外,在进入循环之前,您实际上并没有测试 f(a)f(b) 的原始值是否具有相反的符号。您可以预先对其进行测试,或者将其添加为另一个停止条件(就像我所做的那样)。

    【讨论】:

    • 非常感谢帮助,但我认为我的代码不起作用,它只迭代了一次。我和你做的一模一样
    • 如果我在工作表中的一维或文档中的二维数学中将这两个代码块中的任何一个剪切并粘贴到 Maple(版本 2021.0 或早至 Maple 16.02)中,那么两者都可以正常运行我。如果您完全按照我的说明进行操作,我不相信它对您不起作用,
    • 我已经尝试过了,但它只为我显示了第一个 p `p:=(a+b)/2',在这种情况下是 30。
    • 也许你复制粘贴的方式和我不同。
    猜你喜欢
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多