在编译时简化分数以避免被零除

Simplify fractions at compile time to avoid division by zero

本文关键字:编译      更新时间:2023-10-16

有没有办法在评估之前简化分数以避免被零除?

例:

double x1 = 2;
double x2 = 2;
double x3 = 2;
double r1 = (x1-x2)/(x1-x2-x3);
cout << r1 << endl;
x3 = 0;
r1 = (x1-x2)/(x1-x2-x3);
cout << r1 << endl;

将返回:

-0
-nan

是否可以使编译器在编译时简化第二个表达式以避免被零除?特别是,如果x3等于 0,我希望(x1-x2)/(x1-x2-x3)简化为 1。

在我的代码中,因子x1x2x3被函数取代。

我已经在评论中陈述了以下内容(这听起来可能有点粗鲁,但这只是因为我认为澄清这种误解非常重要):您无法通过简单地重新排列分数或取消来避免除以零。要了解原因,请考虑以下示例:

 x/y

这与

 (0*x) / (0*y)

因为这会大大改变分数的值。通常

 x/y = (a*x) / (a*y)

true,仅当 a 不为 0 时。另一种方法是考虑方程和可能的变换。考虑

a = b

这绝对不一样

0*a = 0*b

(a = b)  is equivalent to (a*x = b*x) 

仅当 x 不为 0 时才成立。

如果你想避免被零除,唯一的方法是检查除数是否为 0 并以某种方式处理这种情况。您无法通过取消 0 来避免被零除,因为这会更改分数的值。

No.特别是,如果 x1、x2、x3 的值是通过函数调用获得的,编译器如何知道 x3 为零,因此表达式简化为 (x1-x2)/(x1-x2) ?

但是,您可以在代码中显式进行所需的测试,以在执行除法之前检查是否有简化表达式的方法。

正如 dim 在他的回答中提到的那样,为什么不直接实施代码检查呢?它将是一个简单的 if 语句,并且与运行时定义的变量兼容。

太糟糕了,我还不能发表评论,因为在你的问题下面有一个关于除以零的有趣且主要是错误的讨论。当然,将 0/0 设置为 1 是有意义的。更重要的是,您向我们展示的 x3 -> x1 - x2 表达式的限制是 1(或 -1,取决于您来自哪里)。这意味着在特殊情况下,其中许多是实际用例,您可能希望将此特定 n/A 设置为 1,以便计算可以继续进行,而不会抱怨不重要(在某些情况下,非物理)无穷大。显然,我让你们在数学上(或至少在物理上)找到该限制的正确用途,因为您并没有确切地告诉我们您想做什么。