Skip to content

Commit

Permalink
fix: Fixed when both operands are zero
Browse files Browse the repository at this point in the history
  • Loading branch information
shinuza committed Jan 3, 2025
1 parent 0db42c1 commit cdf2c44
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 4 deletions.
37 changes: 33 additions & 4 deletions lib/decimal.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

var DECIMAL_SEPARATOR = '.';

import { DivisionByZeroError } from './exceptions.js';

// Decimal
var Decimal = function (num) {
if (this === undefined) {
Expand All @@ -45,7 +47,24 @@ var Decimal = function (num) {
this.internal = String(num);
this.as_int = as_integer(this.internal);

// Helper to normalize zero values
this.normalizeZero = function () {
if (
this.internal === '0' ||
this.internal === '-0' ||
this.internal === '00' ||
this.internal === '000'
) {
return '0';
}
return this.internal;
};

this.add = function (target) {
if ((this.internal === '0' || this.internal === '-0') && (target === '0' || target === '-0')) {
return Decimal('0');
}

var operands = [this, new Decimal(target)];
operands.sort(function (x, y) {
return x.as_int.exp - y.as_int.exp;
Expand All @@ -63,10 +82,17 @@ var Decimal = function (num) {
};

this.sub = function (target) {
if ((this.internal === '0' || this.internal === '-0') && (target === '0' || target === '-0')) {
return Decimal('0');
}
return Decimal(this.add(target * -1));
};

this.mul = function (target) {
if ((this.internal === '0' || this.internal === '-0') && (target === '0' || target === '-0')) {
return Decimal('0');
}

target = new Decimal(target);
var result = String(this.as_int.value * target.as_int.value);
var exp = this.as_int.exp + target.as_int.exp;
Expand All @@ -77,10 +103,14 @@ var Decimal = function (num) {
this.div = function (target) {
target = new Decimal(target);

if (target.internal === '0' || target.internal === '-0') {
throw new DivisionByZeroError('Division by zero');
}

var smallest = Math.min(this.as_int.exp, target.as_int.exp);

var x = Decimal.mul(Math.pow(10, Decimal.abs(smallest).toNumber()), this);
var y = Decimal.mul(Math.pow(10, Decimal.abs(smallest).toNumber()), target);
var x = Decimal.mul(Math.pow(10, Decimal.abs(smallest)), this);
var y = Decimal.mul(Math.pow(10, Decimal.abs(smallest)), target);

return Decimal(x / y);
};
Expand Down Expand Up @@ -158,7 +188,7 @@ var Decimal = function (num) {
};

this.toString = function () {
return this.internal;
return this.normalizeZero();
};

this.toNumber = function () {
Expand Down Expand Up @@ -197,7 +227,6 @@ var as_integer = function (number) {
};
};

// Helpers
// Helpers
var neg_exp = function (str, position, sign) {
position = Decimal.abs(position);
Expand Down
11 changes: 11 additions & 0 deletions lib/exceptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Division by zero error

function DivisionByZeroError(message) {
this.name = 'DivisionByZeroError';
this.message = message || 'Cannot divide by zero';
}
DivisionByZeroError.prototype = Object.create(Error.prototype);
DivisionByZeroError.prototype.constructor = DivisionByZeroError;

// Exports
export { DivisionByZeroError };
49 changes: 49 additions & 0 deletions tests/zero.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { test } from 'node:test';
import assert from 'node:assert';
import Decimal from '../lib/decimal.js';
import { DivisionByZeroError } from '../lib/exceptions.js';

test('zero addition', function (t) {
assert.equal(Decimal('0').add('0').toString(), '0');
assert.equal(Decimal('-0').add('0').toString(), '0');
assert.equal(Decimal('0').add('-0').toString(), '0');
assert.equal(Decimal('-0').add('-0').toString(), '0');

// Static method
assert.equal(Decimal.add('0', '0').toString(), '0');
assert.equal(Decimal.add('-0', '0').toString(), '0');
});

test('zero subtraction', function (t) {
assert.equal(Decimal('0').sub('0').toString(), '0');
assert.equal(Decimal('-0').sub('0').toString(), '0');
assert.equal(Decimal('0').sub('-0').toString(), '0');
assert.equal(Decimal('-0').sub('-0').toString(), '0');

// Static method
assert.equal(Decimal.sub('0', '0').toString(), '0');
assert.equal(Decimal.sub('-0', '0').toString(), '0');
});

test('zero multiplication', function (t) {
assert.equal(Decimal('0').mul('0').toString(), '0');
assert.equal(Decimal('-0').mul('0').toString(), '0');
assert.equal(Decimal('0').mul('-0').toString(), '0');
assert.equal(Decimal('-0').mul('-0').toString(), '0');

// Static method
assert.equal(Decimal.mul('0', '0').toString(), '0');
assert.equal(Decimal.mul('-0', '0').toString(), '0');
});

test('zero division', function (t) {
// Division by zero should throw an error
assert.throws(() => Decimal('0').div('0'), DivisionByZeroError);
assert.throws(() => Decimal('-0').div('0'), DivisionByZeroError);
assert.throws(() => Decimal('0').div('-0'), DivisionByZeroError);
assert.throws(() => Decimal('-0').div('-0'), DivisionByZeroError);

// Static method
assert.throws(() => Decimal.div('0', '0'), DivisionByZeroError);
assert.throws(() => Decimal.div('-0', '0'), DivisionByZeroError);
});

0 comments on commit cdf2c44

Please sign in to comment.