0

Is there a way to simplify fractions prior to evaluation in order to avoid division by zero?

Example:

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;

will return:

-0
-nan

Is it possible to make the compiler simplify the second expression at compile time to avoid the division by zero? In particular, if x3 equals 0, I expect (x1-x2)/(x1-x2-x3) to be simplified to 1.

In my code the factors x1, x2 and x3 are replaced by functions.

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Karrasm
  • 3
  • 4
  • So you would want to get a compilation error like `Division by 0` ? – Unda Apr 27 '16 at 09:25
  • You could write class with template integral parameters and operator double, but then you need rational numbers. – Incomputable Apr 27 '16 at 09:29
  • 1
    Even at compile-time, dividing by zero will make an NaN or Inf, how would that help? – Christopher Oicles Apr 27 '16 at 09:31
  • @Unda: I would like to have the compiler to just perform the cancellation of the fraction prior to evaluation and return 1 instead to -nan. – Karrasm Apr 27 '16 at 09:32
  • what cancelation? 0/0 is not defined no matter how you rearrange it. Making the result to be 1 would lead to very unexpected and wrong results – 463035818_is_not_an_ai Apr 27 '16 at 09:34
  • After performing the division, you could do `if(r1 != r1) { r1 = 1; }` (at run-time) – Christopher Oicles Apr 27 '16 at 09:34
  • 1
    How could it return 1? You're dividing zero by zero... – dgrine Apr 27 '16 at 09:36
  • Just from pure algebra one might just simplify the expression without any consideration of the particular value of x and then you get 1. – Karrasm Apr 27 '16 at 09:39
  • 1
    sorry, but thats just plain wrong. From algebra you should know, that by multiplying both sides of an equation by 0, all information is lost! Same is true for "simplifying" fractions by cancelling out terms that are actually zero. It is just not allowed! – 463035818_is_not_an_ai Apr 27 '16 at 09:41
  • just take an example of x/y .. is this really the same as (0*x) / (0*y) ?? Obvioulsy not, thus also (0*x) / (0*y) is not the same as x/y. qed. – 463035818_is_not_an_ai Apr 27 '16 at 09:42
  • 1
    What are the _real_ problem you are trying to solve here? It seems as if you have already selected a solution, and it might not be the best ;) – Max Value Apr 27 '16 at 09:43
  • @Karrasm You need to understand, that you cannot simplify x/x to 1 in the general case, This simplification is only allowed if x is different from 0. The formula could not have been derived for the case x=0 and you need to go back in the derivation to see the x=0 case. – Micha Wiedenmann Apr 27 '16 at 10:18
  • I'm voting to close this question as off-topic because it operates on the wrong assumption that x/x can be simplified to 1 in the x=0 case. (The OP should probably ask a new, fixed question.) – Micha Wiedenmann Apr 27 '16 at 10:26

3 Answers3

1

I already stated the following in comments (that maybe sounded a bit rude, but thats just because I think it is really important to clear up this misunderstanding): You cannot avoid division by zero by simply rearranging the fraction or doing cancellations. To see why is this, consider this example:

 x/y

This is not the same as

 (0*x) / (0*y)

because this changes the value of the fraction considerably. In general

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

is true, only if a is not 0. Another way to see this is by considering equations and possible transformations. Consider

a = b

this is definitely not the same as

0*a = 0*b

but

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

only holds if x is not 0.

If you want to avoid division by zero, the only way is to check if the divisor is 0 and handle this case in some way. You cannot avoid division by zero by canceling out the 0, because this will change the value of the fraction.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Thank you for pointing this out (I should have remembered it myself though). In deed it leads to an uncovered special case in the formulas I got from literature. – Karrasm Apr 27 '16 at 11:08
0

No. In particular, if the values of x1, x2, x3 are obtains through function call, how would the compiler know that x3 is zero and thus the expression reduces to (x1-x2)/(x1-x2) ?

However, you can just make the required tests explicitly in your code to check if there is a way to simplify the expression before doing the division.

dim
  • 623
  • 8
  • 19
  • Would it help to define the functions as constexpr in order to provide this information at compile time ? – Karrasm Apr 27 '16 at 09:35
  • I could help. But to guarantee compile-time evaluation, you need to assign the value to a compile-time constant. See http://stackoverflow.com/questions/20682915/constexpr-function-not-calculate-value-in-compile-time. Moreover, I'm not sure whether the compiler itself will not stop compilation with a division by zero error, then. – dim Apr 27 '16 at 10:08
0

As dim mentions in his answer, why not just implement code checks? It would be a simple if-statement, and compatible with variables defined at runtime.

Too bad I cannot comment yet, since there is an interesting and mainly wrong discussion about division by zero going on beneath your question. Of course it can make sense to set 0/0 to 1. More to the point, the limit of the expression you show us for x3 -> x1 - x2 is 1 (or -1, depending on where you are coming from). This means that in special cases, many of which are actual use cases, you would want to set this particular n/A to 1, so that a calculation can go forward without complaining about unimportant (and in some cases, unphysical) infinities. I am obviously leaving it up to you to find mathematically (or at least physically) correct uses for that limit, since you are not telling us what you want to do, exactly.

GeckoGeorge
  • 446
  • 1
  • 3
  • 11