0 Replies - 2196 Views - Last Post: 26 March 2014 - 06:19 AM

#1 Dormilich  Icon User is offline

  • 痛覚残留
  • member icon

Reputation: 4138
  • View blog
  • Posts: 13,074
  • Joined: 08-June 10

Complex Number Calculator

Posted 26 March 2014 - 06:19 AM

/**
 * An object representing a complex number supporting the base 
 * calculations (+, , *, /) and the computation of conjugate 
 * complex numbers.
 * The script makes use of ECMAScript 5s property descriptors
 * and thus may only run in appropriate, supporting browsers. The 
 * implementation forces a complete lock-down of the constructor
 * object and the instance properties "re" and "im" are defined
 * through accessors. There should be no issue from deleted or 
 * changed properties now.
 *
 * @author Bertold von Dormilich <Dormilich at netscape dot net>
 * @created October 13, 2011
 */
/**
 * Short API 
 *   METHOD       OPERATION
 * add()            a + b
 * subtract()       a - b
 * subtractFrom()   b - a
 * multiply()       a  b
 * divideBy()       a  b
 * divisionOf()     b  a
 * conjugate()      a* / x - yi
 * absolute()       a  a* / x + y
 * toString()       "x + yi"
 * valueOf()        length / sqrt(aa*) / sqrt(x + y)
 *
 * the static methods are intended for internal use only.
 */

/**
 * constructor for complex number object. both input parameters
 * must evaluate as a number. If a value is assigned to either 
 * "re" or "im", this value is checked for validaty as well.
 *
 * @param (mixed) r     real part of the complex number
 * @param (mixed) i     imaginary part of the complex number
 * @throws (Error)      number conversion failed
 */
function Complex(r, i)
{
    // convert input to number
    function valueToNumber(x)
    {
        x = parseFloat(x);
        if (isNaN(x)) {
            throw new Error("Parameter does not qualify for a complex number.");
        }
        return x;
    }
    // where the values are saved
    r = valueToNumber(r);
    i = valueToNumber(i);
    // definition of the "virtual" properties "re"/"im"
    // this.re
    Object.defineProperty(this, "re", { 
        get : function () { return r; },
        set : function (real) { r = valueToNumber(real); }
    });
    // this.im
    Object.defineProperty(this, "im", { 
        get : function () { return i; },
        set : function (imaginary) { i = valueToNumber(imaginary); }
    });
}
/**
 * create a new complex number based on the addition of the 
 * real/imaginary parameters of two complex numbers.
 *
 * @param (number) r1       real part of the 1st summand
 * @param (number) i1       imaginary part of the 1st summand
 * @param (number) r2       real part of the 2nd summand
 * @param (number) i2       imaginary part of the 2n summand
 * @return (Complex)        complex number of the sum
 */
Complex.addParameters = function (r1, i1, r2, i2)
{
    return new Complex(r1 + r2, i1 + i2);
};
/**
 * add two complex numbers. the 2nd summand may be given as object
 * or via its real/imaginary parameters.
 *
 * @param (mixed) num       either an instance of Complex or a set
 *                          of exactly two numbers representing the 
 *                          real and imaginary part
 * @return (Complex)        complex number of the sum (this + num)
 * @throws (Error)          parameters dont match
 */
Complex.prototype.add = function (num)
{
    if (2 === arguments.length) {
        num = new Complex(arguments[0], arguments[1]);
    }
    if (num instanceof Complex) {
        return Complex.addParameters(this.re, this.im, num.re, num.im);
    }
    throw new Error("Invalid complex number given.");
};
/**
 * create a new complex number based on the subtraction of the 
 * real/imaginary parameters of two complex numbers.
 *
 * @param (number) r1       real part of the minuend
 * @param (number) i1       imaginary part of the minuend
 * @param (number) r2       real part of the subtrahend
 * @param (number) i2       imaginary part of the subtrahend
 * @return (Complex)        complex number of the difference
 */
Complex.subParameters = function (r1, i1, r2, i2)
{
    return new Complex(r1 - r2, i1 - i2);
};
/**
 * subtract two complex numbers. the current instance is the minuend
 * (first term in the difference equation) the given parameter is the
 * subtrahend (second term in the difference equation).
 *
 * @param (mixed) num       either an instance of Complex or a set
 *                          of exactly two numbers representing the 
 *                          real and imaginary part
 * @return (Complex)        complex number of the difference (this - num)
 * @throws (Error)          parameters dont match
 */
Complex.prototype.subtract = function (num)
{
    if (2 === arguments.length) {
        num = new Complex(arguments[0], arguments[1]);
    }
    if (num instanceof Complex) {
        return Complex.subParameters(this.re, this.im, num.re, num.im);
    }
    throw new Error("Invalid complex number given.");
};
/**
 * subtract two complex numbers. the current instance is the subtrahend
 * (second term in the difference equation) the given parameter is the
 * minuend (second term in the difference equation). only useful if the
 * minuend is not given as object, otherwise you should use the subtract()
 * method of the minuend or it used in chaining.
 *
 * @param (mixed) num       either an instance of Complex or a set
 *                          of exactly two numbers representing the 
 *                          real and imaginary part
 * @return (Complex)        complex number of the difference (num - this)
 * @throws (Error)          parameters dont match
 */
Complex.prototype.subtractFrom = function (num)
{
    if (2 === arguments.length) {
        num = new Complex(arguments[0], arguments[1]);
    }
    if (num instanceof Complex) {
        return num.subtract(this);
    }
    throw new Error("Invalid complex number given.");
};
/**
 * create a new complex number based on the multiplication of the 
 * real/imaginary parameters of two complex numbers, based on the 
 * binomial theorem.
 *
 * @param (number) r1       real part of the 1st factor
 * @param (number) i1       imaginary part of 1st factor
 * @param (number) r2       real part of the 2nd factor
 * @param (number) i2       imaginary part of the 2nd factor
 * @return (Complex)        complex number of the product
 */
Complex.multParameters = function (r1, i1, r2, i2)
{
    return new Complex(r1 * r2 - i1 * i2, r1 * i2 + r2 * i1);
};
/**
 * multiply two complex numbers. the 2nd factor may be given as object
 * or via its real/imaginary parameters.
 *
 * @param (mixed) num       either an instance of Complex or a set
 *                          of exactly two numbers representing the 
 *                          real and imaginary part
 * @return (Complex)        complex number of the product (this * num)
 * @throws (Error)          parameters dont match
 */
Complex.prototype.multiply = function (num)
{
    if (2 === arguments.length) {
        num = new Complex(arguments[0], arguments[1]);
    }
    if (num instanceof Complex) {
        return Complex.multParameters(this.re, this.im, num.re, num.im);
    }
    throw new Error("Invalid complex number given.");
};
/**
 * divide two complex numbers. the divisor may be given as object
 * or via its real/imaginary parameters. complex division is done
 * according to the binomial theorem: a  b = (a  b*)  (b  b*)
 * [b* - complex conjugate of b; bb* is always a real number]
 *
 * @param (mixed) num       divisor, either an instance of Complex or
 *                          a set of exactly two numbers representing 
 *                          the real and imaginary part
 * @return (Complex)        complex number of the quotient (this  num)
 * @throws (Error)          parameters dont match
 */
Complex.prototype.divideBy = function (num)
{
    if (2 === arguments.length) {
        num = new Complex(arguments[0], arguments[1]);
    }
    if (num instanceof Complex) {
        var abs  = num.absolute(),                      // bb*
            prod = num.conjugate().multiply(this);      // ab*
        prod.re /= abs;
        prod.im /= abs;
        return prod;
    }
    throw new Error("Invalid complex number given.");
};
/**
 * same as divideBy() only with divisor and dividend exchanged. 
 * allows to divide the current instance from a number given as
 * parameters or for chaining.
 *
 * @param (mixed) num       dividend, either an instance of Complex or
 *                          a set of exactly two numbers representing 
 *                          the real and imaginary part
 * @return (Complex)        complex number of the quotient (num  this)
 * @throws (Error)          parameters dont match
 */
Complex.prototype.divisionOf = function (num)
{
    if (2 === arguments.length) {
        num = new Complex(arguments[0], arguments[1]);
    }
    if (num instanceof Complex) {
        return num.divideBy(this);
    }
    throw new Error("Invalid complex number given.");
};
/**
 * create the conjugate complex number. if n = a + bi, the conjugate
 * complex is n* = a - bi. useful in many mathematical operations
 * (related to Matrix algebra).
 *
 * @return (Complex)        conjugate complex number 
 */
Complex.prototype.conjugate = function ()
{
    return new Complex(this.re, -1 * this.im);
};
/**
 * result of the operation nn*. equivalent to the square of the 
 * vectorial length of the complex number in the complex plane. 
 *
 * @return (number)         conjugate complex number 
 */
Complex.prototype.absolute = function ()
{
    return this.conjugate().multiply(this).re;
};
/**
 * string representation as: a + bi. used in Javascript when a string
 * representation is required, e.g. for printing values to the document.
 *
 * @param (number) acc      number of post decimal positions
 * @return (string)         rectangular expression of the complex number
 */
Complex.prototype.toString = function (acc)
{
    var re = this.re,
        im = Math.abs(this.im);
    
    if ((typeof acc == "number") && (acc >= 0)) {
        re = re.toFixed(acc);
        im = im.toFixed(acc);
    }
    if (0 === this.im) {
        return re;
    }
    return re + (this.im < 0 ? "  " : " + ") + (1 == im ? "i" : im + "i");
};
/**
 * length of the vector in rectangular expression of the complex number.
 * used in Javascript operations that require a number, e.g. 2 * c.
 *
 * @return (number)         length value of the complex number
 */
Complex.prototype.valueOf = function ()
{
    return Math.sqrt(this.absolute());
};

// prevent further modifications of the Complex object
Object.freeze(Complex);



Usage:
//create complex numbers:
var c1 = new Complex(1, 2); // 1 + 2i
var c2 = new Complex(1, -1); // 1 - i

// add
c1.add(c2);
// add using parameters: c1 + (-1 + 2i)
c1.add(-1, 2);
// display
document.form_name.text_field.value = c1.multiply(c2); 


Is This A Good Question/Topic? 0
  • +

Page 1 of 1