tough-rational
Version:
Rational class using BigInt with fallback to bignumber.js
234 lines (229 loc) • 8.26 kB
JavaScript
'use strict';
const Rational = require('../');
const RationalFallback = require('../lib/rational-fallback');
const { expect } = require('chai');
const compat = require('../lib/compat');
const util = require('../lib/util');
if (compat.testForBigInt()) describe('rational class', () => {
it('should do cmp', () => {
expect(Rational(1).cmp(1)).to.eql(0);
expect(Rational(0).cmp(1)).to.eql(-1);
expect(Rational(1).cmp(0)).to.eql(1);
});
it('should round', () => {
expect(String(Rational(0.5).round())).to.eql('1');
});
it('should add', () => {
const rat = new Rational(5.5).plus(5.5);
expect(rat.numerator).to.eql(BigInt(11));
expect(rat.denominator).to.eql(BigInt(1));
});
it('should subtract', () => {
const rat = new Rational(5.5).minus(2);
expect(rat.numerator).to.eql(BigInt(7));
expect(rat.denominator).to.eql(BigInt(2));
});
it('should multiply', () => {
const rat = new Rational(2.5).multiply(2.5);
expect(rat.numerator).to.eql(BigInt(25));
expect(rat.denominator).to.eql(BigInt(4));
});
it('should do fp division', () => {
const rat = new Rational(2.5).dividedBy(2.3);
expect(rat.numerator).to.eql(BigInt(25));
expect(rat.denominator).to.eql(BigInt(23));
});
it('should do integer division', () => {
const rat = new Rational(2.5).dividedToIntegerBy(2.3);
expect(rat.numerator).to.eql(BigInt(1));
expect(rat.denominator).to.eql(BigInt(1));
});
it('should find absolute value', () => {
const rat = new Rational(2.5).abs();
expect(rat.numerator).to.eql(BigInt(5));
expect(rat.denominator).to.eql(BigInt(2));
const otherRat = new Rational(-2.5).abs();
expect(rat.numerator).to.eql(BigInt(5));
expect(rat.denominator).to.eql(BigInt(2));
});
it('should do pow10', () => {
const rat = new Rational(10).pow10(3);
expect(rat.numerator).to.eql(BigInt(10000));
});
it('should do div10', () => {
const rat = new Rational(10).div10(3);
expect(rat.numerator).to.eql(BigInt(1));
expect(rat.denominator).to.eql(BigInt(100));
});
it('should exponentiate', () => {
const rat = new Rational(10).pow(2);
expect(rat.numerator).to.eql(BigInt(100));
expect(rat.denominator).to.eql(BigInt(1));
});
it('should serialize to a string', () => {
const rat = new Rational(5.5);
expect(String(rat)).to.eql('5.5');
});
it('should mod', () => {
const rat = new Rational(3.6);
expect(String(rat.mod(3))).to.eql('0.6');
});
it('should do comparison operators', () => {
const a = new Rational(3.6);
const b = new Rational(4.2);
expect(a.gt(b)).to.be.false;
expect(a.gt(3.6)).to.be.false;
expect(a.gt(3.5)).to.be.true;
expect(a.lt(b)).to.be.true;
expect(a.lt(3.5)).to.be.false;
expect(a.geq(3.5)).to.be.true;
expect(a.geq(3.6)).to.be.true;
expect(a.geq(3.7)).to.be.false;
expect(a.leq(3.5)).to.be.false;
expect(a.leq(3.6)).to.be.true;
expect(a.leq(3.7)).to.be.true;
expect(a.eq(3.6)).to.be.true;
expect(a.eq(3.5)).to.be.false;
expect(a.neq(3.6)).to.be.false;
expect(a.neq(3.5)).to.be.true;
expect(a.isZero()).to.be.false;
expect(Rational(0).isZero()).to.be.true;
expect(a.isNonZero()).to.be.true;
expect(Rational(0).isNonZero()).to.be.false;
expect(a.gtZero()).to.be.true;
expect(a.ltZero()).to.be.false;
expect(Rational(-1).gtZero()).to.be.false;
expect(Rational(-1).ltZero()).to.be.true;
});
it('should tell if it\'s floating point', () => {
expect(Rational(1.5).isFloatingPoint()).to.be.true;
expect(Rational(1).isFloatingPoint()).to.be.false;
});
it('should do floor and ceil', () => {
expect(String(Rational(1.5).ceil())).to.eql('2');
expect(String(Rational(1.5).floor())).to.eql('1');
});
it('should do a shift left', () => {
expect(String(Rational(1).shiftLeft(2))).to.eql('4');
});
it('should do a shift right', () => {
expect(Rational(256).shiftRight(2).eq(64)).to.be.true;
});
it('should do a toHexString', () => {
expect(Rational(4096).toHexString()).to.eql('0x1000');
});
});
describe('rational fallback class', () => {
it('should add', () => {
const rat = new RationalFallback(5.5).plus(5.5);
expect(String(rat)).to.eql('11');
});
it('should subtract', () => {
const rat = new RationalFallback(5.5).minus(2);
expect(String(rat)).to.eql('3.5');
});
it('should multiply', () => {
const rat = new RationalFallback(2.5).multiply(2.5);
expect(String(rat)).to.eql('6.25');
});
it('should do fp division', () => {
const rat = new RationalFallback(5.76).dividedBy(4.8);
expect(String(rat)).to.eql('1.2');
});
it('should do integer division', () => {
const rat = new RationalFallback(2.5).dividedToIntegerBy(2.3);
expect(String(rat)).to.eql('1');
});
it('should find absolute value', () => {
const rat = new RationalFallback(2.5).abs();
expect(String(rat)).to.eql('2.5');
const otherRat = new RationalFallback(-2.5).abs();
expect(String(otherRat)).to.eql('2.5');
});
it('should do pow10', () => {
const rat = new RationalFallback(10).pow10(3);
expect(String(rat)).to.eql('10000');
});
it('should do div10', () => {
const rat = new RationalFallback(10).div10(3);
expect(String(rat)).to.eql('0.01');
});
it('should exponentiate', () => {
const rat = new RationalFallback(10).pow(2);
expect(String(rat)).to.eql('100');
});
it('should serialize to a string', () => {
const rat = new RationalFallback(5.5);
expect(String(rat)).to.eql('5.5');
});
it('should mod', () => {
const rat = new RationalFallback(3.6);
expect(String(rat.mod(3))).to.eql('0.6');
});
it('should do comparison operators', () => {
const a = new RationalFallback(3.6);
const b = new RationalFallback(4.2);
expect(a.gt(b)).to.be.false;
expect(a.gt(3.6)).to.be.false;
expect(a.gt(3.5)).to.be.true;
expect(a.lt(b)).to.be.true;
expect(a.lt(3.5)).to.be.false;
expect(a.geq(3.5)).to.be.true;
expect(a.geq(3.6)).to.be.true;
expect(a.geq(3.7)).to.be.false;
expect(a.leq(3.5)).to.be.false;
expect(a.leq(3.6)).to.be.true;
expect(a.leq(3.7)).to.be.true;
expect(a.eq(3.6)).to.be.true;
expect(a.eq(3.5)).to.be.false;
expect(a.neq(3.6)).to.be.false;
expect(a.neq(3.5)).to.be.true;
expect(a.isZero()).to.be.false;
expect(RationalFallback(0).isZero()).to.be.true;
expect(a.isNonZero()).to.be.true;
expect(RationalFallback(0).isNonZero()).to.be.false;
expect(a.gtZero()).to.be.true;
expect(a.ltZero()).to.be.false;
expect(RationalFallback(-1).gtZero()).to.be.false;
expect(RationalFallback(-1).ltZero()).to.be.true;
});
it('should tell if it\'s floating point', () => {
expect(RationalFallback(1.5).isFloatingPoint()).to.be.true;
expect(RationalFallback(1).isFloatingPoint()).to.be.false;
});
it('should do floor and ceil', () => {
expect(String(RationalFallback(1.5).ceil())).to.eql('2');
expect(String(RationalFallback(1.5).floor())).to.eql('1');
});
it('should do a shift left', () => {
expect(String(RationalFallback(1).shiftLeft(2))).to.eql('4');
});
it('should do a shift right', () => {
expect(RationalFallback(256).shiftRight(2).eq(64)).to.be.true;
});
it('should do a toHexString', () => {
expect(RationalFallback(4096).toHexString()).to.eql('0x1000');
});
it('should do toHexStringStripped', () => {
expect(RationalFallback(256).toHexStringStripped()).to.eql('0x100');
});
it('should do toHexString on a large int', () => {
expect(String(RationalFallback(String(29000000000000)).toHexString())).to.eql('0x1a6016b2d000');
});
it('should do round', () => {
expect(String(RationalFallback('0.5').round())).to.eql('1');
});
it('should do cmp', () => {
expect(RationalFallback(1).cmp(1)).to.eql(0);
expect(RationalFallback(0).cmp(1)).to.eql(-1);
expect(RationalFallback(1).cmp(0)).to.eql(1);
});
});
describe('rational utilities', () => {
it('should padLeft', () => {
const padTo = 8;
const padChar = '0';
const fn = util.leftPad(padChar)(padTo);
expect(fn(Array(5).join(padChar))).to.eql(Array(padTo + 1).join(padChar));
});
});