Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does (inf + 0j)*1 evaluate to inf + nanj?

>>> (float('inf')+0j)*1 (inf+nanj) 

Why? This caused a nasty bug in my code.

Why isn't 1 the multiplicative identity, giving (inf + 0j)?

like image 640
marnix Avatar asked Sep 20 '19 16:09

marnix


People also ask

What causes INF Python?

We can define the negative infinity as -inf and the positive infinity as inf in Python. In mathematics, sqrt(-1) in real numbers or 0/0 (zero over zero) gives an undefined number, which can be defined as Nan . In data science, Nan is used to represent the missing values in a dataset.

What does INF output mean in Python?

Definition and Usage inf constant returns a floating-point positive infinity. For negative infinity, use -math. inf .

What is INF data type?

inf is infinity - a value that is greater than any other value. -inf is therefore smaller than any other value. nan stands for Not A Number, and this is not equal to 0 .

What are INFS or nans?

Inf and -Inf are positive and negative infinity whereas NaN means 'Not a Number'. (These apply to numeric values and real and imaginary parts of complex values but not to values of integer vectors.) Inf and NaN are reserved words in the R language.


2 Answers

The 1 is converted to a complex number first, 1 + 0j, which then leads to an inf * 0 multiplication, resulting in a nan.

(inf + 0j) * 1 (inf + 0j) * (1 + 0j) inf * 1  + inf * 0j  + 0j * 1 + 0j * 0j #          ^ this is where it comes from inf  + nan j  + 0j - 0 inf  + nan j 
like image 110
Marat Avatar answered Oct 14 '22 10:10

Marat


Mechanistically, the accepted answer is, of course, correct, but I would argue that a deeper ansswer can be given.

First, it is useful to clarify the question as @PeterCordes does in a comment: "Is there a multiplicative identity for complex numbers that does work on inf + 0j?" or in other words is what OP sees a weakness in the computer implementation of complex multiplication or is there something conceptually unsound with inf+0j

Short answer:

Using polar coordinates we can view complex multiplication as a scaling and a rotation. Rotating an infinite "arm" even by 0 degrees as in the case of multiplying by one we cannot expect to place its tip with finite precision. So indeed, there is something fundamentally not right with inf+0j, namely, that as soon as we are at infinity a finite offset becomes meaningless.

Long answer:

Background: The "big thing" around which this question revolves is the matter of extending a system of numbers (think reals or complex numbers). One reason one might want to do that is to add some concept of infinity, or to "compactify" if one happens to be a mathematician. There are other reasons, too (https://en.wikipedia.org/wiki/Galois_theory, https://en.wikipedia.org/wiki/Non-standard_analysis), but we are not interested in those here.

One point compactification

The tricky bit about such an extension is, of course, that we want these new numbers to fit into the existing arithmetic. The simplest way is to add a single element at infinity (https://en.wikipedia.org/wiki/Alexandroff_extension) and make it equal anything but zero divided by zero. This works for the reals (https://en.wikipedia.org/wiki/Projectively_extended_real_line) and the complex numbers (https://en.wikipedia.org/wiki/Riemann_sphere).

Other extensions ...

While the one point compactification is simple and mathematically sound, "richer" extensions comprising multiple infinties have been sought. The IEEE 754 standard for real floating point numbers has +inf and -inf (https://en.wikipedia.org/wiki/Extended_real_number_line). Looks natural and straightforward but already forces us to jump through hoops and invent stuff like -0 https://en.wikipedia.org/wiki/Signed_zero

... of the complex plane

What about more-than-one-inf extensions of the complex plane?

In computers, complex numbers are typically implemented by sticking two fp reals together one for the real and one for the imaginary part. That is perfectly fine as long as everything is finite. As soon, however, as infinities are considered things become tricky.

The complex plane has a natural rotational symmetry, which ties in nicely with complex arithmetic as multiplying the entire plane by e^phij is the same as a phi radian rotation around 0.

That annex G thing

Now, to keep things simple, complex fp simply uses the extensions (+/-inf, nan etc.) of the underlying real number implementation. This choice may seem so natural it isn't even perceived as a choice, but let's take a closer look at what it implies. A simple visualization of this extension of the complex plane looks like (I = infinite, f = finite, 0 = 0)

I IIIIIIIII I               I fffffffff I I fffffffff I I fffffffff I I fffffffff I I ffff0ffff I I fffffffff I I fffffffff I I fffffffff I I fffffffff I               I IIIIIIIII I 

But since a true complex plane is one that respects complex multiplication, a more informative projection would be

     III      I         I       fffff        fffffff      fffffffff   I fffffffff I I ffff0ffff I I fffffffff I   fffffffff      fffffff        fffff      I         I       III     

In this projection we see the "uneven distribution" of infinities that is not only ugly but also the root of problems of the kind OP has suffered: Most infinities (those of the forms (+/-inf, finite) and (finite, +/-inf) are lumped together at the four principal directions all other directions are represented by just four infinities (+/-inf, +-inf). It shouldn't come as a surprise that extending complex multiplication to this geometry is a nightmare.

Annex G of the C99 spec tries its best to make it work, including bending the rules on how inf and nan interact (essentially inf trumps nan). OP's problem is sidestepped by not promoting reals and a proposed purely imaginary type to complex, but having the real 1 behave differently from the complex 1 doesn't strike me as a solution. Tellingly, Annex G stops short of fully specifying what the product of two infinities should be.

Can we do better?

It is tempting to try and fix these problems by choosing a better geometry of infinities. In analogy to the extended real line we could add one infinity for each direction. This construction is similar to the projective plane but doesn't lump together opposite directions. Infinities would be represented in polar coordinates inf x e^{2 omega pi i}, defining products would be straightforward. In particular, OP's problem would be solved quite naturally.

But this is where the good news ends. In a way we can be hurled back to square one by---not unreasonably---requiring that our newstyle infinities support functions that extract their real or imaginary parts. Addition is another problem; adding two nonantipodal infinities we'd have to set the angle to undefined i.e. nan (one could argue the angle must lie between the two input angles but there is no simple way of representing that "partial nan-ness")

Riemann to the rescue

In view of all this maybe the good old one point compactification is the safest thing to do. Maybe the authors of Annex G felt the same when mandating a function cproj that lumps all the infinities together.


Here is a related question answered by people more competent on the subject matter than I am.

like image 45
Paul Panzer Avatar answered Oct 14 '22 09:10

Paul Panzer