# Strange inconsistent in complex algebra

**URL:** <https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851>\
**Category:** General Usage\
**Created:** [April 1, 2020, 2:27pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851 "2020-04-01T14:27:47Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 1, 2020, 2:27pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/1 "2020-04-01T14:27:47Z")

</div>

The following code generate different result

```julia
1 Complex((-0.5) * 0.5^2)^(-0.2)
2. ((-0.5) * Complex(0.5)^2)^(-0.2)

```

I run the code in Julia 1.1, the results are as following

 ![WeChat5ee163d53a6edba3513427ce01b36e31](https://global.discourse-cdn.com/julialang/original/3X/5/b/5b75fc8f8e717706396b9b8fe844fd37dafe8fcd.png)

I thinks the point is how to define (-1)\*(0.0im).

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [April 1, 2020, 2:36pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/2 "2020-04-01T14:36:45Z")

</div>

Zeros are signed: 0.0 is different from -0.0 (in julia, `0.0 == -0.0` but `!isequal(0.0, -0.0)`). In the first example you have a x + 0.0im. In the second example you have (-0.5) \* (x + 0.0im) = -0.5x - 0.0im. The complex power relies on the log, which has a branch cut around the negative axis:

```julia
julia> log(-1 + 0.0im)
0.0 + 3.141592653589793im

julia> log(-1 - 0.0im)
0.0 - 3.141592653589793im

```

So everything is consistent. Floating-point arithmetic is annoying…

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 1, 2020, 2:38pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/3 "2020-04-01T14:38:02Z")

</div>

Yeah, the difference is that `Complex((-0.5) * 0.5^2)=-0.125 + 0.0im`, but `((-0.5) * Complex(0.5)^2)=-0.125 - 0.0im`. This is, as you suspected because `-1*0.0im=-0.0im` as floating point arithmetic dictates.

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 1, 2020, 2:48pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/4 "2020-04-01T14:48:38Z")

</div>

So the problem is in the Complex function. Perhaps I can define a new complex function that  
`Complexnew(x:: Float64)=x+0im`  
instead of  
`Complex(x:: Float64)=x+0.0im`

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 1, 2020, 2:50pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/5 "2020-04-01T14:50:55Z")

</div>

That won’t fix anything. The problem is that everything here is working as designed. It’s just IEEE arithmetic being annoying.

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 1, 2020, 2:55pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/6 "2020-04-01T14:55:38Z")

</div>

But in mathematic, we know 0=-0. Complex a real number x should generate x+0im

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 1, 2020, 2:58pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/7 "2020-04-01T14:58:01Z")

</div>

It does, the problem is that `Complex(0.5)^2)=0.25+0.0im`. Multiplying that by `-.5` gives `-.125-0.0im`.

In floating point arithmetic, `0.0==-0.0`, but hey are **not** the same number. For example, `1.0/0.0=inf`, but `1.0/-0.0=-inf`

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [April 1, 2020, 3:03pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/8 "2020-04-01T15:03:54Z")

</div>

Of course the problem is that you’re looking a holomorphic function _on_ its branch cut, or dividing by zero or so on. Don’t do that and everything’s fine.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 1, 2020, 3:35pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/9 "2020-04-01T15:35:38Z")

</div>

> [@Oscar\_Smith](#):
>
> It’s just IEEE arithmetic being annoying.

AFAIK there is a rationale for signed zeros, especially for complex functions. William Kahan has some papers about the reasons ([eg this one](https://homes.cs.washington.edu/~ztatlock/599z-17sp/papers/branch-cuts-kahan-87.pdf)).

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 1, 2020, 3:55pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/10 "2020-04-01T15:55:22Z")

</div>

I agree with this point. In math, we usually need an infinitely small number in complex algebra. It seems that 0.0 in Julia is to this end. That is the reason that 0.0≠-0.0 does make sense. But complexify a real number should generate a number which is of exact vanishing imagine part. So that why I think complex(x) should be x+0im. Otherwise, it will generate “wrong” results in scientific computing.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 1, 2020, 4:16pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/11 "2020-04-01T16:16:04Z")

</div>

Both of the answers are correct, they are just choosing a different side of the branch cut. Which side of the branch cut is selected depends on the sign of the imaginary part, i.e. the sign of zero.

Not being able to choose the branch cut would be even worse. Consider:

```julia
julia> z = Complex(-1)
-1 + 0im

julia> sqrt(z)
0.0 + 1.0im

```

Now, when we compute `1/z`, the arithmetic rules are smart enough to flip the sign of the zero in the imaginary part:

```julia
julia> 1/z
-1.0 - 0.0im

```

This gives the nice property that `sqrt(1/z)` and `sqrt(z)` return the same thing, -i:

```julia
julia> sqrt(1/z)
0.0 - 1.0im

julia> 1/sqrt(z)
0.0 - 1.0im

```

On the other hand, suppose that `sqrt(1/z)` ignored the sign of the zero in the imaginary part (or there was no signed zero). Since `1/z == -1`, such a naive rule would return \sqrt{1/z} = +i \ne 1/\sqrt{z} = 1/i = -i. (Returning either +i or -i from \sqrt{-1} are both perfectly correct in the sense that (\pm i)^2 = -1, but it is important to be _consistent_ about the choice of branch cut.)

If you are dealing with multi-valued functions of complex numbers, like exponentiation, you need to be aware of branch cuts and understand their consequences for your problem. But rest assured that a _lot_ of thought went into the IEEE rules for complex arithmetic (which pre-date Julia by decades and are nearly universally followed in computer programming languages).

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 1, 2020, 4:47pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/12 "2020-04-01T16:47:32Z")

</div>

Agree, both the result are correct. But in practice, there is a canonical way to choose the branch. In Mathematica, it does make such a choice. The choice in Mathematica can keep the equation 0\*anything=0 hold. If Julia can make such a choice of the branch automatically, it will be better.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 1, 2020, 5:03pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/13 "2020-04-01T17:03:53Z")

</div>

The problem with that is that according to C, Python, IEEE, your processor, and basically everyone in computer science, that is wrong. If you really want this behavior, you can define

```julia
function smul(x,y)
    if x==zero(x)
        return zero(x)*zero(y)
    elseif y==zero(y)
       return zero(y)*zero(y)
    else
          return x*y
    end
end

```

which will do what you want. It will often be much slower though.

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 1, 2020, 5:20pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/14 "2020-04-01T17:20:42Z")

</div>

Thanks for the code. Sorry, I thinks I word “wrong” is not proper in my last reply. As @stevengj mentioned, they are all correct. But in practice especially in complicated science computing, the result is easy to be justified or compared between the different methods if Julia can fix the branch automatically.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 1, 2020, 5:26pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/15 "2020-04-01T17:26:18Z")

</div>

Julia will not change which branch is taken since it currently takes the correct branches. It will also not change what multiplication of `0.0im` by negatives is since the current behavior is not only correct, but also the only fast behavior due to processor floating point units.

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 1, 2020, 5:32pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/16 "2020-04-01T17:32:52Z")

</div>

Then Julia perhaps will lost some people in science computing. The Mathematica actually make the natural branch from either math or physics point of view. It also keeps the fast behavior. BTW, I am not talking about the 0.0im, but 0im,

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 1, 2020, 5:36pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/17 "2020-04-01T17:36:27Z")

</div>

Oh, I just re-read what you say you want. The problem with `Complex(x::float64)=x+0im` is that then your complex object has a different real and imaginary type. `0` is an integer, so that would mean your number did everything really weirdly. For example, `(1.0+0im)*1.0=1.0+0.0im` due to promotion. In short, this would not be a good idea at all.

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 1, 2020, 5:43pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/18 "2020-04-01T17:43:17Z")

</div>

I agree. It should not like this. I need to think about other tricks to make choice of the branch efficiently.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 1, 2020, 5:44pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/19 "2020-04-01T17:44:29Z")

</div>

> [@gangchern](#):
>
> Then Julia perhaps will lost some people in science computing.

As we keep emphasizing, these rules don’t come from Julia. They are the same in Fortran, C, C++, Numpy, … any language that needs to do high-performance computation uses hardware arithmetic and follows IEEE rules. When you use [“machine numbers”](https://reference.wolfram.com/language/tutorial/Numbers.html) in Mathematica they also use IEEE arithmetic (and hence have signed zero etc.).

That is, virtually everyone doing practical scientific computation has already accepted these rules.

> If Julia can make such a choice of the branch automatically, it will be better.

Julia (really, IEEE rules) _does_ choose the branch automatically. If you have a number right on the branch cut, it uses the sign of zero to choose the side. This is the most self-consistent choice in finite-precision floating-point arithmetic (“machine numbers” in Mathematica-speak).

---

<div class="post-metadata">

**Author:** ![gangchern](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gangchern/32/13298_2.png) [@gangchern](https://discourse.julialang.org/u/gangchern)\
**Post date:** [April 1, 2020, 6:11pm UTC](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851/20 "2020-04-01T18:11:31Z")

</div>

I know that. I am not mean to change the current “complex” function or “power” functions. That choice of the branch does make sense and keep the efficient in lots of science and engineer problem. However, it (IEEE rule) is not so convenient for some problem because the rule make the equation 0\*anything=0 seems not hold. In my current problem, the out put result of the function can have millions of branches. If two different methods give their own result in different branches, although they are all correct. It still need to spend lot of time to check the results. As far as I know, Julia have many similar pattens with Mathematica in defining the Functions. So if Mathematica can make such branch choice naturally. Julia should be also possible in principle.

[Next page](https://discourse.julialang.org/t/strange-inconsistent-in-complex-algebra/36851.md?page=2)
