Skip to content

Instantly share code, notes, and snippets.

@jbruni
Last active September 25, 2018 22:07
Show Gist options
  • Save jbruni/3004a783369a60931e2baf644440d129 to your computer and use it in GitHub Desktop.
Save jbruni/3004a783369a60931e2baf644440d129 to your computer and use it in GitHub Desktop.
Math functions suitable for monetary calculations
/**
* Basic Arithmetic
*/
const bind = Function.prototype.bind,
liberate = bind.bind(Function.prototype.call),
reduce = liberate(Array.prototype.reduce),
slice = liberate(Array.prototype.slice);
function multiplier(x) {
const parts = x.toString().split('.');
if (parts.length < 2) {
return 1;
}
return Math.pow(10, parts[1].length);
}
function correctionFactor() {
return reduce(arguments, function (prev, next) {
const mp = multiplier(prev),
mn = multiplier(next);
return mp > mn ? mp : mn;
}, -Infinity);
}
export function add() {
var corrFactor = correctionFactor.apply(null, arguments);
function cback(accum, curr, currI, O) {
return accum + corrFactor * curr;
}
return reduce(arguments, cback, 0) / corrFactor;
}
export function sub() {
var corrFactor = correctionFactor.apply(null, arguments),
first = arguments[0];
function cback(accum, curr, currI, O) {
return accum - corrFactor * curr;
}
delete arguments[0];
return reduce(arguments,
cback, first * corrFactor) / corrFactor;
}
export function mul() {
function cback(accum, curr, currI, O) {
var corrFactor = correctionFactor(accum, curr);
return (accum * corrFactor) * (curr * corrFactor) /
(corrFactor * corrFactor);
}
return reduce(arguments, cback, 1);
}
export function div() {
function cback(accum, curr, currI, O) {
var corrFactor = correctionFactor(accum, curr);
return (accum * corrFactor) / (curr * corrFactor);
}
return reduce(arguments, cback);
}
// Taken from https://github.com/guipn/sinful.js
void function (bless) {
'use strict';
var bind = Function.prototype.bind,
liberate = bind.bind(Function.prototype.call),
reduce = liberate(Array.prototype.reduce),
slice = liberate(Array.prototype.slice);
bless = bless || function (thing, name, content) {
if (typeof thing[name] !== 'undefined') {
throw new Error('Sinful: ' + name + ' is already defined.');
}
thing[name] = content;
};
function multiplier(x) {
var parts = x.toString().split('.');
if (parts.length < 2) {
return 1;
}
return Math.pow(10, parts[1].length);
}
function correctionFactor() {
return reduce(arguments, function (prev, next) {
var mp = multiplier(prev),
mn = multiplier(next);
return mp > mn ? mp : mn;
}, -Infinity);
}
[
[Math, 'add', function () {
var corrFactor = correctionFactor.apply(null, arguments);
function cback(accum, curr, currI, O) {
return accum + corrFactor * curr;
}
return reduce(arguments, cback, 0) / corrFactor;
}],
[Math, 'sub', function () {
var corrFactor = correctionFactor.apply(null, arguments),
first = arguments[0];
function cback(accum, curr, currI, O) {
return accum - corrFactor * curr;
}
delete arguments[0];
return reduce(arguments,
cback, first * corrFactor) / corrFactor;
}],
[Math, 'mul', function () {
function cback(accum, curr, currI, O) {
var corrFactor = correctionFactor(accum, curr);
return (accum * corrFactor) * (curr * corrFactor) /
(corrFactor * corrFactor);
}
return reduce(arguments, cback, 1);
}],
[Math, 'div', function () {
function cback(accum, curr, currI, O) {
var corrFactor = correctionFactor(accum, curr);
return (accum * corrFactor) / (curr * corrFactor);
}
return reduce(arguments, cback);
}],
].forEach(function (blessing) {
bless(blessing.shift(), blessing.shift(), blessing.shift());
});
}();
@jbruni
Copy link
Author

jbruni commented Sep 25, 2018

I have removed the wrapping code and the Math prototype changes from the original sinful.js code.

The result is at basic-math.js file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment