5
$\begingroup$

Many languages like R, Julia, and Python store imaginary numbers as a complex number with a 0 valued real component. We may see this with the following R code:

I_x <- 3i
C_y <- Inf + 2i
z <- I_x * C_y

If R had a datatype for imaginary numbers, z would equal -6 + Infi, but the result is NaN + Infi because the imaginary is implemented by a complex number with a zero real component (3i is 0 + 3i) so a NaN arises from the multiplication of the 0 component by Inf.

A commenter notes that languages may special-case the multiplication of two complex numbers together, so another test case which would discriminate that could be to see the result of (in R) Inf * 1i which results in NaN + Infi.

My question is, which languages provide a built-in imaginary data type which is not implemented as a complex type with a 0 valued real component? A good answer should show the output to the above or an equivalent test case or point to language documentation. There will probably be multiple good answers.

To be specific, I am looking for languages with built-in types, not the capacity to create imaginary types or libraries which can be downloaded and provide these types.

$\endgroup$
11
  • 3
    $\begingroup$ refer to www2.eecs.berkeley.edu/Pubs/TechRpts/1992/CSD-92-667.pdf $\endgroup$
    – Moonchild
    Commented Feb 3 at 4:00
  • 8
    $\begingroup$ Frame challenge: I'm not sure that complex numbers with separate inf/nan components should be considered as legitimate in the first place. In mathematics, complex analysis uses the concept of "complex infinity" which is a complex number of "infinite" magnitude and indeterminate angle (as well as "directed infinities" that are the positive-infinitely scaled version of some finite complex number). Complex numbers should theoretically be untouched by converting from rectangular to polar and back; infinities throw a wrench in that. $\endgroup$ Commented Feb 3 at 10:47
  • 3
    $\begingroup$ Are you interested in libraries that come with the language or not? These fall between your terms "built-in" and "downloadable". I'm particularly thinking of C++ and C support for complex numbers in their respective Standard libraries. $\endgroup$ Commented Feb 3 at 12:58
  • 2
    $\begingroup$ There's also the matter of interpretation; if I declare type Imaginary = number; in TypeScript, for example, does this type represent an imaginary number? It supports binary +, unary and binary -, and multiplication by real numbers, which are the only arithmetic you can do with imaginary numbers. Sure, if you use binary * on two such "imaginary" numbers you'll get a nonsense answer, but that's only because binary * itself doesn't make sense within the space of imaginary numbers. $\endgroup$
    – kaya3
    Commented Feb 5 at 18:33
  • 2
    $\begingroup$ @AdamHyland If a language returns either of those things then it's not a true complex number type, in the mathematical sense, since neither of those are complex numbers. $\endgroup$
    – kaya3
    Commented Feb 5 at 18:48

6 Answers 6

8
$\begingroup$

Wolfram

The programming language used by Mathematica not only supports pure imaginary numbers, but offers rigorous treatment of infinite complex values.

(3 * I) * (Infinity + 2*I)

Wolfram considers that "infinity + 2*i" simply gives infinity, because in complex analysis, the finite imaginary component added to a real infinity just can't be preserved: either way, the result is a complex value with an infinite magnitude and an argument (angle, in the r-cis-theta sense) of zero.

(Infinity * (0 + I))

Some syntax quirk on Wolfram Alpha seems to prevent multiplying real-infinity with i directly, but this way works.

It also recognizes a "directed infinity" concept (which I alluded to above): a complex value with an infinite magnitude and some known argument. As expected, multiplication by i effectively rotates by 90 degrees in the complex plane, and adding a finite offset has no effect:

DirectedInfinity[1+I] * I

DirectedInfinity[1+I] + 1

There's also a "complex infinity" concept representing the "circle at infinity" in complex analysis (some value with an infinite magnitude and unknown argument):

ComplexInfinity * I

ComplexInfinity + 1

$\endgroup$
7
$\begingroup$

Results are below:

Languages

Snap! and Ruby both pass the original test case, but Ruby does not pass a simpler one suggested by user23013.

Maple passes the original test case and user23013's other test case.

Snap!

The Snap! programming language is one example which will pass the above test case and return -6 + Infi. You can copy and play around with related code here.

Snap! building blocks showing definition of infinity and result of z value

Ruby

Ruby also has an imaginary type (run the code):

# Define the complex numbers
three_i = Complex(0, 3)
infinity_plus_two_i = Complex(1.0/0.0, 2) # 1.0/0.0 creates Infinity in Ruby
# Perform the multiplication
result = three_i * infinity_plus_two_i
# Display the result
puts "#{result}"

Output is -6.0+Infinity*i

A comment notes that this may be "a special case for multiplying two complex numbers and "Ruby gives NaN+Infinity*i for Complex(0,1)*(1.0/0) ".

Maple

(infinity + 2*I) * 3*I results in -6 + infinity*I

(0 + I) * infinity returns infinity * I, while (0 + I) * (1/0) produces a numeric error due to division by zero.

$\endgroup$
2
  • $\begingroup$ Ruby gives NaN+Infinity*i for Complex(0,1)*(1.0/0). It's probably a special case for multiplying two complex numbers instead of anything internally stored as imaginary. $\endgroup$
    – user23013
    Commented Feb 2 at 21:58
  • $\begingroup$ thanks for this! I'll update the question with this as a different test case. $\endgroup$ Commented Feb 2 at 22:03
2
$\begingroup$

At least two languages of the C family provide complex numbers either built-in or as part of the standard library defined in the language specification.

C

The language has three built-in complex types: double _Complex, float _Complex and long double _Complex (unless the implementation defines __STDC_NO_COMPLEX__). It may also have three imaginary types: double _Imaginary, float _Imaginary and long double _Imaginary.

If the standard library header <complex.h> is included, simpler names for these are defined (double complex, float complex and long double complex, respectively), as well as a full set of mathematical functions on complex types analogous to those provided for floating-point numbers.

(specification)

I don't have an environment supporting pure imaginary numbers, only complex. On this system, the test fails:

#include <complex.h>
#include <stdio.h>
#include <math.h>

int main(void)
{
    double complex I_x = 3 * I;
    double complex C_y = INFINITY + 2 * I;
    double complex z = I_x * C_y;

    printf("%e%+e·i\n", creal(z), cimag(z));
}
-nan+inf·i

However, it's conceivable that other C implementations produce different results if they provide the pure imaginary type.

C++

The C++ standard library defines a complex<T> template that can be used to create a complex version of any arithmetic type. Similar to C, the standard header <complex> provides a full set of mathematical functions, generally with the same names as their scalar counterparts. Pure imaginary numbers don't exist - they are represented by complex numbers with a zero real component.

Namespace std::literals::complex_literals provides suffix notation for literals of imaginary double, float or long double type.

(specification)

This fails your test:

#include <complex>
#include <iostream>
#include <limits>

int main()
{
    using namespace std::literals::complex_literals;
    auto Inf = std::numeric_limits<double>::infinity();
    auto I_x = 3i;
    auto C_y = Inf + 2i;
    auto z = I_x * C_y;

    std::cout << z << '\n';
}
(-nan,inf)
$\endgroup$
1
  • 1
    $\begingroup$ I appreciate this detailed answer, even though the result is negative. Ideally this question will grow to have many answers and someone who finds it won't be left speculating about the performance of important languages like C and C++. Thank you. $\endgroup$ Commented Feb 7 at 19:24
2
$\begingroup$

Go

Go has two built-in complex types: complex64 and complex128, being a pair of float32 and float64 respectively. It also has imaginary literals, but all it does is return a complex number with a real value set to 0, so Go doesn't pass the tests in the OP.

ix := 3i
cy := complex(0,math.Inf(1)) + 2i
z := ix * cy

fmt.Println("ix", ix) // ix (0+3i)
fmt.Println("cy", cy) // cy (0+Infi)
fmt.Println("z", z)   // z (-Inf+NaNi)

Attempt This Online!

There are 3 built-in functions for complex numbers:

  • complex(realPart, imaginaryPart floatT) complexT: construct a complex number from a given pair of floats.
  • real(complexT) floatT: get the real portion of a complex number.
  • imag(complexT) floatT: get the imaginary portion of a complex number.

There are also more functions available in the math/cmplx package.

$\endgroup$
2
$\begingroup$

Reference

https://en.wikipedia.org/wiki/Complex_data_type

Some Examples

Maxima

Maxima: This language provides extensive support for complex and imaginary number arithmetic, featuring functions like cabs for the magnitude of complex numbers and rectform to express complex numbers in rectangular form. Similar to Wolfram Language, Maxima can handle operations involving infinities within the complex number system.

Try it online!

/* Define complex numbers */
z1 : 3 + 4*%i;
z2 : 1 - 2*%i;

/* Complex number arithmetic */
sum : z1 + z2;
product : z1 * z2;
quotient : z1 / z2;

/* Simplify results */
simp_sum : fullratsimp(sum);   /* 2 %i + 4  */
simp_product : fullratsimp(product);  /* 11 - 2 %i  */
simp_quotient : fullratsimp(quotient);

/* Output simplified results */
print("Simplified Sum: ", simp_sum);
print("Simplified Product: ", simp_product);
print("Simplified Quotient: ", simp_quotient);

/* Working with infinity */
infinityPlus : inf + (3 + 4*%i);
infinityTimes : inf*%i * z1;

/* Output results with infinity */
print("Infinity plus (3+4i): ", fullratsimp(infinityPlus)); /* inf + 4 %i + 3  */
print("Infinity times (3+4i): ", fullratsimp(infinityTimes)); /*  (3 %i - 4) inf   */
$\endgroup$
3
  • $\begingroup$ This answer mostly repeats what is in the other answers, but also without addressing the core question about languages with an imaginary type distinct from a complex number with zero real component. $\endgroup$
    – Michael Homer
    Commented Apr 21 at 3:15
  • 1
    $\begingroup$ I see that it's been edited quite dramatically in its history - there were probably some good points about C99 now removed as well. Maxima hadn't been mentioned previously, although as you say it's mostly within a complex number type (but the results of the test calculations from the question aren't given - those could help). I think editing it to give answers that aren't in the existing answers would help, including if those answers are mistaken about some relevant aspect of a language you do also mention. $\endgroup$
    – Michael Homer
    Commented Apr 21 at 3:18
  • $\begingroup$ Thank you for adding another example language with code! $\endgroup$ Commented Apr 21 at 18:09
1
$\begingroup$

Of the compiled programming languages, (I believe) it is Ada, C (but only some compilers), Chapel, and D.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .