2016年8月7日日曜日

開発環境

加減乗除できるようになったところまで。(異なる型同士でも演算可能に。)

コード(Emacs)

var RADIX = Math.pow(10, 5),
    NUM_SIZE = Math.log10(RADIX);

Number.prototype.neg = function () {
    var n = this.valueOf();

    if (n === 0) {
        return 0;
    }
    return -this.valueOf();
};
Number.prototype.getSign = function () {
    var n = this.valueOf();
    
    if (n < 0) {
        return -1;
    }
    if (n === 0) {
        return 0;
    }
    if (n > 0) {
        return 1;
    }
};
Number.prototype.isZero = function () {
    return this.getSign() === 0;
};
Number.prototype.isPositive = function () {
    return this.getSign() === 1;
};
Number.prototype.isNegative = function () {
    return this.getSign() === -1;
};
Number.prototype.isEqual =function (z) {
    if (typeof z === 'number') {
        return this.valueOf() === z;
    }
    return z.isEqual(this.valueOf());
};
Complex = function (real, imag) {
    var real = real,
        imag = imag;

    this.getReal = function () {
        return real;
    };
    this.getImag = function () {
        return imag;
    };
};
Number.prototype.toComplex = function () {
    return new Complex(this.valueOf(), 0);
};
Complex.prototype = new Number();
Complex.prototype.toString = function () {
    var real = this.getReal(),
        imag = this.getImag(),
        str = real.toString();

    if (imag  === 0) {
        return str;
    }
    if (imag > 0) {
        str  += '+';
    }
    if (imag === 1) {
        str += 'i';
    } else if (imag === -1) {
        str += '-i';
    } else {
        str += imag + 'i';
    }
    return str;
};
Complex.prototype.toString = function () {
    var real = this.getReal(),
        imag = this.getImag(),
        str = real.toString();

    if (imag  === 0) {
        return str;
    }
    if (imag > 0) {
        str  += '+';
    }
    if (imag === 1) {
        str += 'i';
    } else if (imag === -1) {
        str += '-i';
    } else {
        str += imag + 'i';
    }
    return str;
};
Complex.prototype.isEqual = function (z) {
    if (z instanceof Integer ||
        z instanceof Rational ||
        typeof(z) === 'number') {
        return this.isEqual(z.toComplex());
    }
    return this.getReal() === z.getReal() && this.getImag() === z.getImag();
};
Complex.prototype.neg = function () {
    return new Complex(this.getReal().neg(), this.getImag().neg());
};
Complex.prototype.conjugate = function () {
    return new Complex(this.getReal(), this.getImag().neg());
};
Complex.prototype.isReal = function() {
    return this.getImag() === 0;
};
Complex.prototype.getSign = function () {
    var real;
    if (this.isReal()) {
        real = this.getReal();
        if (real > 0) {
            return 1;
        }
        if (real === 0) {
            return 0;
        }
        if (real < 0) {
            return -1;
        }
    }
    throw {
        type: 'getSign',
        message: 'wrong type argument: ' + this
    };
};
Complex.prototype.isZero = function () {
    if (this.isReal()) {
        return this.getSign() === 0;
    }
    return this.getReal().isZero() && this.getImag().isZero();
};
Complex.prototype.isPositive = function () {
    return this.getSign() === 1;
};
Complex.prototype.isNegative = function () {
    return this.getSign() === -1;
};
Complex.prototype.add = function (z) {
    if (z instanceof Integer ||
        z instanceof Rational ||
        typeof(z) === 'number') {
        return this.add(z.toComplex());
    }
    return new Complex(this.getReal() + z.getReal(),
                       this.getImag() + z.getImag());
};
Complex.prototype.sub = function (z) {
    if (z instanceof Integer ||
        z instanceof Rational ||
        typeof(z) === 'number') {
        return this.sub(z.toComplex());
    }
    return new Complex(this.getReal() - z.getReal(),
                       this.getImag() - z.getImag());
};
Complex.prototype.mul = function (z) {
    if (z instanceof Integer ||
        z instanceof Rational ||
        typeof(z) === 'number') {
        return this.mul(z.toComplex());
    }
    var real = this.getReal() * z.getReal() - this.getImag() * z.getImag(),
        imag = this.getReal() * z.getImag() + this.getImag() * z.getReal();
    
    return new Complex(real, imag);
};
Complex.prototype.div = function (z) {
    if (z instanceof Integer ||
        z instanceof Rational ||
        typeof(z) === 'number') {
        return this.div(z.toComplex());
    }
    var z1 = z.conjugate(),
        z2 = this.mul(z1),
        n = z.mul(z1).getReal(),
        real = z2.getReal() / n,
        imag = z2.getImag() / n;

    return new Complex(real, imag);
};
Complex.prototype.lt = function (z) {
    return this.sub(z).isNegative();
};
Complex.prototype.le = function (z) {
    return this.isEqual(z) || this.lt(z);
};
Complex.prototype.gt = function (z) {
    return this.sub(z).isPositive();
};
Complex.prototype.ge = function (z) {
    return this.isEqual(z) || this.gt(z);
};
Number.prototype = new Complex();
Number.prototype.constructor = Number;
Number.prototype.lt = function (z) {
    return this.sub(z).isNegative();
};
Number.prototype.le = function (z) {
    return this.isEqual(z) || this.lt(z);
};
Number.prototype.gt = function (z) {
    return this.sub(z).isPositive();
};
Number.prototype.ge = function (z) {
    return this.isEqual(z) || this.lt(z);
};
Number.prototype.add = function (z) {
    if (z instanceof Complex) {
        return this.toComplex().add(z);
    }
    if (typeof z === 'number') {
        return this.valueOf() + z;
    }
    return this.add(z.toNumber());
};
Number.prototype.sub = function (z) {
    if (z instanceof Complex) {
        return this.toComplex().sub(z);
    }
    if (typeof z === 'number') {
        return this.valueOf() - z;
    }
    return this.sub(z.toNumber());
};
Number.prototype.mul = function (z) {
    if (z instanceof Complex) {
        return this.toComplex().mul(z);
    }
    if (typeof z === 'number') {
        return this.valueOf() * z;
    }
    return this.mul(z.toNumber());
};
Number.prototype.div = function (z) {
    if (z instanceof Complex) {
        return this.toComplex().div(z);
    }
    if (typeof z === 'number') {
        return this.valueOf() / z;
    }
    return this.div(z.toNumber());
};
Rational = function (num, den) {    
    var num = num,
        den = den,
        sign;
    
    if (num.isZero()) {
        sign = 0;
    } else {        
        sign = num.getSign() * den.getSign();
    }
    num = num.abs();
    den = den.abs();
    this.getSign = function () {
        return sign;
    }
    this.getNumerator = function () {
        return num;
    };
    this.setNumerator = function (n) {
        sign *= n.getSign();
        num = n.abs();
    };
    this.getDenominator = function () {
        return den;
    };
    this.setDenominator = function (n) {
        sign *= n.getSign();
        den = n.abs();
    };
};
Rational.prototype.toNumber = function () {
    var sign = this.getSign(),
        num,
        den,
        q,
        r;

    if (sign === 0) {
        return 0;
    }
    num = this.getNumerator().abs();
    den = this.getDenominator().abs();
    q = num.floorQuotient(den);
    r = num.floorRemainder(den);
    return q.add(r.toNumber().div(den));
};
Rational.prototype.toComplex = function () {
    return new Complex(this.toNumber(), 0);
};
Rational.prototype.toString = function () {
    var num,
        den,
        result = '';
    
    this.canonicalize();
    if (this.getSign() === -1) {
        result += '-';
    }
    num = this.getNumerator();
    den = this.getDenominator();

    result += num + '/' + den;
    
    return result;
};
Rational.prototype.isEqual = function (z) {
    if (z instanceof Integer) {
        return this.isEqual(z.toRational());
    }
    if (typeof z === 'number') {
        return this.toNumber().isEqual(z);
    }
    if (z instanceof Complex) {
        return this.toComplex().isEqual(z);
    }
    this.canonicalize();
    z.canonicalize();
    return this.toString() === z.toString();
};
Rational.prototype.lt = function (z) {
    return this.sub(z).isNegative();
};
Rational.prototype.le = function (z) {
    return this.isEqual(z) || this.lt(z);
};
Rational.prototype.gt = function (z) {
    return this.sub(z).isPositive();
};
Rational.prototype.ge = function (z) {
    return this.isEqual(z) || this.gt(z);
};
Rational.prototype.canonicalize = function () {
    var num = this.getNumerator(),
        den = this.getDenominator(),
        g = num.gcd(den);

    this.setNumerator(num.floorQuotient(g));
    this.setDenominator(den.floorQuotient(g));
};
Rational.prototype.neg = function () {
    return this.mul(new Integer('-1'));
};
Rational.prototype.isZero = function () {
    return this.getSign() === 0;
};
Rational.prototype.isPositive = function () {
    return this.getSign() === 1;
};
Rational.prototype.isNegative = function () {
    return this.getSign() === -1;
};
Rational.prototype.add = function (z) {
    if (z instanceof Integer) {
        return this.add(z.toRational());
    }
    if (typeof z === 'number') {
        return this.toNumber().add(z);
    }
    if (z instanceof Complex) {
        return this.toComplex().add(z);
    }
    var num1 = this.getNumerator(),
        den1 = this.getDenominator(),
        sign1 = this.getSign(),
        num2 = z.getNumerator(),
        den2 = z.getDenominator(),
        sign2 = z.getSign();

    if (sign1 === -1) {
        num1 = num1.neg();
    }
    if (sign2 === -1) {
        num2 = num2.neg();
    }
    return new Rational(num1.mul(den2).add(num2.mul(den1)), den1.mul(den2));
};
Rational.prototype.sub = function (z) {
    return this.add(z.neg());
};
Rational.prototype.mul = function (z) {
    if (z instanceof Integer) {
        return this.mul(z.toRational());
    }
    if (typeof z === 'number') {
        return this.toNumber().mul(z);
    }
    if (z instanceof Complex) {
        return this.toComplex().mul(z);
    }
    var sign = this.getSign() * z.getSign();
    sign = new Integer(sign.toString());
    return new Rational(this.getNumerator().mul(z.getNumerator()).mul(sign),
                        this.getDenominator().mul(z.getDenominator()));

};
Rational.prototype.div = function (z) {
    if (z instanceof Integer) {
        return this.toRational().div(z);
    }
    if (typeof z === 'number') {
        return this.toNumber().div(z);
    }
    if (z instanceof Complex) {
        return this.toComplex().div(z);
    }    
    var sign = this.getSign() * z.getSign();
    sign = new Integer(sign.toString());
    return new Rational(this.getNumerator().mul(z.getDenominator()).mul(sign),
                        this.getDenominator().mul(z.getNumerator()));
};
Integer = function (s) {    
    var sign = 1,
        nums = [],
        len = 0,
        s0 = s;

    if (s0 === '0') {
        sign = 0;
    }
    if (s0[0] === '-') {
        sign = -1;
        s0 = s0.slice(1);
    }    
    nums.push(parseInt(s0.slice(-NUM_SIZE), 10));
    s0 = s0.slice(0, -NUM_SIZE);
    for (len = s0.length; len !== 0; len = s0.length) {
        nums.push(parseInt(s0.slice(-NUM_SIZE), 10));
        s0 = s0.slice(0, -NUM_SIZE);
    }
    this.getSign = function () {
        return sign;
    };
    this.getNums = function () {
        return nums.slice();
    };
    this.copy = function () {
        return new Integer(s);
    };
};
Integer.prototype.toRational = function () {
    return new Rational(this, new Integer('1'));
};
Integer.prototype.toNumber = function () {
    return parseFloat(this.toString());
};
Integer.prototype.toComplex = function () {
    return this.toRational().toComplex();
};
Integer.prototype.toString = function () {
    var result = '',
        nums = this.getNums(),
        len = nums.length,
        i,
        s,
        flag = false;

    if (this.getSign() === -1) {
        result += '-';
    } 
    for (i = len; i > 0; i -= 1) {
        s = nums[i - 1].toString();
        if (flag) {
            if (s.length < NUM_SIZE) {
                result += new Array(NUM_SIZE - s.length + 1).join('0');
            }
        } else {
            flag = true;
        }
        result += s;
    }
    return result;
};
Integer.prototype.isEqual = function (z) {
    if (z instanceof Rational) {
        return this.toRational().isEqual(z);
    }
    if (typeof z === 'number') {
        return this.toNumber().isEqual(z);
    }
    if (z instanceof Complex) {
        return this.toComplex().isEqual(z);
    }
    return this.toString() === z.toString();
};
Integer.prototype.lt = function (z) {
    return this.sub(z).isNegative();
};
Integer.prototype.le = function (z) {
    return this.isEqual(z) || this.lt(z);
};
Integer.prototype.gt = function (z) {
    return this.sub(z).isPositive();
};
Integer.prototype.ge = function (z) {
    return this.isEqual(z) || this.gt(z);
};
Integer.prototype.gcd = function (n) {
    var x = this.abs(),
        y = n.abs(),
        q = x.floorQuotient(y),
        r = x.floorRemainder(y);

    if (r.isZero()) {
        return y;        
    }    
    return y.gcd(r);
};

Integer.prototype.neg = function () {
    var s = this.toString();

    if (s[0] === '-')  {
        return new Integer(s.slice(1));
    }
    return new Integer('-' + s);
};
Integer.prototype.isZero = function () {
    return this.getSign() === 0;
};
Integer.prototype.isPositive = function () {
    return this.getSign() === 1;
};
Integer.prototype.isNegative = function () {
    return this.getSign() === -1;
};
Integer.prototype.factorial = function () {
    var result = new Integer('1'),
        t = new Integer(this.toString()),
        one = new Integer('1');

    for (;t.isPositive(); t = t.sub(one)) {
        result = result.mul(t);        
    }
    return result;
};
Integer.prototype.add = function (z) {
    if (z instanceof Rational) {
        return this.toRational().add(z);
    }
    if (typeof z === 'number') {
        return this.toNumber().add(z);
    }
    if (z instanceof Complex) {
        return this.toComplex().add(z);
    }
    var nums1 = this.getNums(),
        sign1 = this.getSign(),
        len1 = nums1.length,
        nums2 = z.getNums(),
        sign2 = z.getSign(),
        len2 = nums2.length,
        nums3,
        nums4,
        len3,
        len4,
        sign3,
        n,
        a = 0,
        b,
        i,
        result = '',
        s,
        flag;

    if (len1 > len2) {
        nums3 = nums1;
        len3 = len1;
        sign3 = sign1;
        nums4 = nums2;
        len4 = len2;
    } else if (len1 < len2) {
        nums3 = nums2;
        len3 = len2;
        sign3 = sign2;
        nums4 = nums1;
        len4 = len1;
    } else if (nums1[len1 - 1] > nums2[len1 - 1]) {
        nums3 = nums1;
        len3 = len1;
        sign3 = sign1;
        nums4 = nums2;
        len4 = len2;
    } else {
        nums3 = nums2;
        len3 = len2;
        sign3 = sign2;
        nums4 = nums1;
        len4 = len1;
    }        
    if (sign1 === sign2) {
        for (i = 0; i < len4; i += 1) {
            n = nums3[i] + nums4[i] + a;
            if (n >= RADIX) {
                a = 1;
                b = n - RADIX;
            } else {
                a = 0;
                b = n;
            }
            nums3[i] = b;
        }
        for (i = len4; i < len3; i += 1) {
            n = nums3[i] + a;
            if (n >= RADIX) {
                a = 1;
                nums3[i] = n - RADIX;
            } else {
                a = 0;
                break;
            }            
        }
        if (a !== 0) {
            nums3[i] = a;
        }
        if (sign1 === -1) {
            result += '-';
        }
    } else {
        for (i = 0; i < len4; i += 1) {
            nums3[i] -= a;
            if (nums3[i] < nums4[i]) {
                a = 1;
                nums3[i] += RADIX;
            } else {
                a = 0;
            }        
            nums3[i] -= nums4[i];        
        }    
        for (i = len4; i < len3; i += 1) {
            nums3[i] -= a;
            if (nums3[i] < 0) {
                a = 1;
                nums3[i] += RADIX;
            } else {
                break;
            }
        }    
        for (i = len3; i > 0; i -= 1) {
            if (nums3[i - 1] === 0) {
                nums3.pop();
            } else {
                break;
            }
        }
        if (i === 0) {
            return new Integer("0");
        }
        if (sign3 === -1) {
            result += '-';
        }
    }
    flag = false;
    for (i = nums3.length; i > 0; i -= 1) {
        s = nums3[i - 1].toString();
        if (flag) {
            if (s.length < NUM_SIZE) {
                result += new Array(NUM_SIZE - s.length + 1).join('0');
            }
        } else {
            flag = true;
        }
        result += s;
    }
    return new Integer(result);
};
Integer.prototype.mul = function (z) {
    if (z instanceof Rational) {
        return this.toRational().mul(z);
    }
    if (typeof z === 'number') {
        return this.toNumber().mul(z);
    }
    if (z instanceof Complex) {
        return this.toComplex().mul(z);
    }    
    var nums1 = this.getNums(),
        sign1 = this.getSign(),
        len1 = nums1.length,
        nums2 = z.getNums(),
        sign2 = z.getSign(),
        len2 = nums2.length,
        nums3 = [],
        sign3 = sign1 * sign2,
        len3,
        n,
        a,
        b,
        i,
        j,
        result = '',
        s,
        flag = false;

    for (j = 0; j < len2; j += 1) {
        for (i = 0; i < len1; i += 1) {
            if (nums3[j + i] === undefined) {
                nums3[j + i] = nums1[i] * nums2[j];
            } else {
                nums3[j + i] += nums1[i] * nums2[j];
            }
        }
    }
    a = 0;
    for (i = 0, len3 = nums3.length; i < len3; i += 1) {
        n = nums3[i] + a;
        a = Math.floor(n / RADIX);
        b = n % RADIX;
        nums3[i] = b;
    }
    if (a !== 0) {
        nums3[i] = a;
    }
    if (sign3 === -1) {
        result += '-';
    }
    flag = false;
    for (i = nums3.length; i > 0; i -= 1) {
        s = nums3[i - 1].toString();
        if (flag) {
            if (s.length < NUM_SIZE) {
                result += new Array(NUM_SIZE - s.length + 1).join('0');
            }
        } else {
            flag = true;
        }
        result += s;
    }
    return new Integer(result);
};
Integer.prototype.sub = function (z) {
    return this.add(z.neg());
};
Integer.prototype.div = function (z) {
    if (z instanceof Rational) {
        return this.toRational().div(z);
    }
    if (typeof z === 'number') {
        return this.toNumber().div(z);
    }
    if (z instanceof Complex) {
        return this.toComplex().div(z);
    }
    return new Rational(this, z);
};
Integer.prototype.abs = function () {
    if (this.isPositive() || this.isZero()) {
        return this.copy();
    }
    return this.neg();
};
Integer.prototype.floorQuotient = function (n) {
    var n1 = this.copy(),
        n2 = n.copy(),
        one = new Integer('1'),
        q = new Integer('0');
    
    if (n.isZero()) {
        return NaN;
    }
    if (this.isZero()) {
        return this.copy();
    }
    if (this.isPositive() && n.isPositive()) {
        for (; n1.ge(n2);) {
            q = q.add(one);
            n1 = n1.sub(n2);
        }
        return q;
    }
    if (this.isPositive() && n.isNegative()) {
        for (; n1.isPositive();) {
            q = q.sub(one);
            n1 = n1.add(n2);
        }
        return q;
    }
    if (this.isNegative() && n.isPositive()) {
        for (; n1.isNegative(); ) {
            q = q.sub(one);
            n1 = n1.add(n2);            
        }
        return q;
    }
    if (this.isNegative() && n.isNegative()) {
        for (; n1.le(n2); ) {
            q = q.add(one);
            n1 = n1.sub(n2);
        }
        return q;
    }
    throw {
        type: 'unknown',
        message: 'Integer floorQuotient',
    }
};
Integer.prototype.floorRemainder = function (n) {
    return this.sub(n.mul(this.floorQuotient(n)));
};

0 コメント:

コメントを投稿