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

Simplify fractions at compile time to avoid division by zero

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

示例:

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;

将return:

-0
-nan

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

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

没有。特别是,如果通过函数调用获得 x1、x2、x3 的值,编译器如何知道 x3 为零,从而将表达式简化为 (x1-x2)/(x1-x2) ?

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

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

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

我已经在评论中陈述了以下内容(这可能听起来有点粗鲁,但这只是因为我认为消除这种误解真的很重要):你不能通过简单地重新排列分数或做取消。要了解这是为什么,请考虑以下示例:

 x/y

这与

不同
 (0*x) / (0*y)

因为这会显着改变分数的值。一般

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

为真,仅当 a而非0。另一种看待这一点的方法是考虑方程式和可能的变换。考虑

a = b

这和

绝对不一样
0*a = 0*b

但是

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

仅当 x 不为 0 时成立。

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