1

In particular, the class doesn't have much in the way of data structure definitions of complex numbers. You could represent it by:

struct complex{
  double real;
  double imaginary;

};

But the imaginary number i = sqrt(-1) cannot be reduced to a primitive type since primitive numerical types are necessarily real numbers. So it would have to be defined implicitly by means of the complex product. This is very easy to do in an object oriented language that allows operator overloading but how is it done with a procedural language like C?

SavedbyZer0
  • 125
  • 1
  • 11
  • 3
    You would use function calls for each of the operations. – Tom Karzes Nov 06 '17 at 02:20
  • 2
    `complex.h`...you can use that also? (built in functionality for complexy numbers)Or else...you need to create method for handling each of the operation – user2736738 Nov 06 '17 at 02:24
  • 3
    "*primitive numerical types are necessarily real numbers*" - no, C has built in complex numbers. – melpomene Nov 06 '17 at 02:25
  • 1
    There is support for a complex type. Also, [see this](https://stackoverflow.com/a/9860772/1983495). – Iharob Al Asimi Nov 06 '17 at 02:25
  • 1
    Note that floating-point types are **not** real numbers. Keeping that in mind will save you a great deal of grief in the future. – Pete Becker Nov 06 '17 at 02:49
  • @PeteBecker real floating point types are of course real numbers save for infinities and nans. But those numbers are also always rational numbers with divisor being a power of two... – Antti Haapala -- Слава Україні Nov 06 '17 at 04:20
  • @AnttiHaapala — every rational number is a real number, but rational numbers do not have all of the properties of real numbers, so it not correct to say that rational numbers are real numbers. Equating the two leads to fundamental misunderstandings of how floating-point math works. – Pete Becker Nov 06 '17 at 13:38
  • @melpomene but how does one represent the imaginary number i in binary? The issue is that the exponentiation of i is periodic(modulo 4). – SavedbyZer0 Nov 11 '17 at 06:29
  • 1
    @SavedbyZer0 As far as I know the standard representation of complex numbers is a pair of real numbers, so i would be (0, 1). – melpomene Nov 11 '17 at 07:49

2 Answers2

2

You can write:

_Complex double x = _Complex_I;

You can do the usual arithmetic operations on complex numbers. The header #include <complex.h> declares complex versions of the usual math functions (trig, roots etc.)

M.M
  • 138,810
  • 21
  • 208
  • 365
  • The standard says you write `double _Complex` — and does not mention `_Complex double`. Can you identify the compiler that allows what you wrote? – Jonathan Leffler Nov 06 '17 at 04:42
  • @JonathanLeffler I don't wish to research any specific compiler behaviour . The standard permits `_Complex double` and `double _Complex`; any compiler that rejects one of those would be bugged. – M.M Nov 06 '17 at 04:54
  • I presume the examples in the Standard use a particular order for the sake of consistency. `long unsigned int` is never mentioned by the standard either, but it is allowed. C11 6.7.2/2 specifically says that the order doesn't matter. – M.M Nov 06 '17 at 04:58
  • OK. You could quote §6.7.2 ¶2: _At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each struct declaration and type name. Each list of type specifiers shall be one of the following multisets (delimited by commas, when there is more than one multiset per item); the type specifiers may occur in any order, possibly intermixed with the other declaration specifiers._ …As you just noted in your comment... One of the lists referred to is `double _Complex`. I'd not seen things written in the reverse order. – Jonathan Leffler Nov 06 '17 at 04:59
  • OK. I just meant to give an example, not provide a full specification :) OP seemed to be unaware of `_Complex` entirely. – M.M Nov 06 '17 at 04:59
  • The header `` also has a macro `I`, that is the one that is supposed as a user interface for either `_Complex_I` or `_Imaginary_I`. – Jens Gustedt Nov 06 '17 at 09:24
2

Section §6.2.5 Types of the C11 standard (ISO/IEC 9899:2011) says, in part:

¶10 There are three real floating types, designated as float, double, and long double.42) The set of values of the type float is a subset of the set of values of the type double; the set of values of the type double is a subset of the set of values of the type long double.

¶11 There are three complex types, designated as float _Complex, double _Complex, and long double _Complex.43) (Complex types are a conditional feature that implementations need not support; see 6.10.8.3.) The real floating and complex types are collectively called the floating types.

¶12 For each floating type there is a corresponding real type, which is always a real floating type. For real floating types, it is the same type. For complex types, it is the type given by deleting the keyword _Complex from the type name.

¶13 Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.

42) See ‘‘future language directions’’ (6.11.1).
43) A specification for imaginary types is in annex G.

6.11.1 Floating types

¶1 Future standardization may include additional floating-point types, including those with greater range, precision, or both than long double.

There's also the library specification §7.3 Complex arithmetic <complex.h>:

7.3.1 Introduction

¶1 The header <complex.h> defines macros and declares functions that support complex arithmetic.192)

¶2 Implementations that define the macro __STDC_NO_COMPLEX__ need not provide this header nor support any of its facilities.

¶3 Each synopsis specifies a family of functions consisting of a principal function with one or more double complex parameters and a double complex or double return value; and other functions with the same name but with f and l suffixes which are corresponding functions with float and long double parameters and return values.

4 The macro

complex

expands to _Complex; the macro

_Complex_I

expands to a constant expression of type const float _Complex, with the value of the imaginary unit.193)

¶5 The macros

imaginary

and

_Imaginary_I

are defined if and only if the implementation supports imaginary types;194) if defined, they expand to _Imaginary and a constant expression of type const float _Imaginary with the value of the imaginary unit.

¶6 The macro

I

expands to either _Imaginary_I or _Complex_I. If _Imaginary_I is not defined, I shall expand to _Complex_I.

¶7 Notwithstanding the provisions of 7.1.3, a program may undefine and perhaps then redefine the macros complex, imaginary, and I.

192) See ‘‘future library directions’’ (7.31.1).
193) The imaginary unit is a number i such that i2 = −1.
194) A specification for imaginary types is in informative annex G.

And there's a 14-page Annex G, which starts:

Annex G

(normative)

IEC 60559-compatible complex arithmetic

G.1 Introduction

¶1 This annex supplements annex F to specify complex arithmetic for compatibility with IEC 60559 real floating-point arithmetic. An implementation that defines __STDC_IEC_559_COMPLEX__ shall conform to the specifications in this annex.375)

375) Implementations that do not define __STDC_IEC_559_COMPLEX__ are not required to conform to these specifications.

G.2 Types

¶1 There is a new keyword _Imaginary, which is used to specify imaginary types. It is used as a type specifier within declaration specifiers in the same way as _Complex is (thus, _Imaginary float is a valid type name).

¶2 There are three imaginary types, designated as float _Imaginary, double _Imaginary, and long double _Imaginary. The imaginary types (along with the real floating and complex types) are floating types.

¶3 For imaginary types, the corresponding real type is given by deleting the keyword _Imaginary from the type name.

¶4 Each imaginary type has the same representation and alignment requirements as the corresponding real type. The value of an object of imaginary type is the value of the real representation times the imaginary unit.

¶5 The imaginary type domain comprises the imaginary types.


It's curious that footnote 194 designates Annex G as 'informative' but the Annex identifies itself as 'normative'. Footnote 43 does mention 'normative' or 'informative'.


Section 6.2.5 ¶13 of the C standard is quite clear about how a complex variable shall be represented.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278