Last active
October 1, 2019 07:58
-
-
Save mx-rk-quyenl/c9c8afc1f9894fc3d6558bafb2660490 to your computer and use it in GitHub Desktop.
Javascript decimal, calc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let DECIMAL_SEPARATOR = '.' | |
let asInteger = (number) => { | |
number = String(number) | |
// var value, exp, tokens = number.split(DECIMAL_SEPARATOR), integer = tokens[0], fractional = tokens[1]; | |
let value = number.split(DECIMAL_SEPARATOR) | |
let exp = value | |
let tokens = value | |
let integer = tokens[0] | |
let fractional = tokens[1] | |
if (!fractional) { | |
let trailingZeros = integer.match(/0+$/) | |
if (trailingZeros) { | |
let length = trailingZeros[0].length | |
value = integer.substr(0, integer.length - length) | |
exp = length | |
} else { | |
value = integer | |
exp = 0 | |
} | |
} else { | |
value = parseInt(number.split(DECIMAL_SEPARATOR).join(''), 10) | |
exp = fractional.length * -1 | |
} | |
return { | |
'value': value, | |
'exp': exp | |
} | |
} | |
// Helpers | |
let zero = (exp) => { | |
return new Array(exp + 1).join('0') | |
} | |
let negExp = (str, position) => { | |
position = Math.abs(position) | |
let flag = str < 0 | |
let offset = position - (flag ? str.split('-')[1].length : str.length) | |
let sep = DECIMAL_SEPARATOR | |
if (offset >= 0) { | |
str = zero(offset) + (flag ? str.split('-')[1] : str) | |
sep = '0.' | |
} | |
let length = str.length | |
let head = str.substr(0, length - position) | |
let tail = str.substring(length - position, length) | |
if (flag) { | |
if (head < 0) return head + sep + tail | |
return '-' + head + sep + tail | |
} | |
return head + sep + tail | |
} | |
let posExp = (str, exp) => { | |
let zeros = zero(exp) | |
return String(str + zeros) | |
} | |
let format = (num, exp) => { | |
num = String(num) | |
let func = exp >= 0 ? posExp : negExp | |
return func(num, exp) | |
} | |
/** | |
* Class Decimal for calculate number | |
*/ | |
export default class Decimal { | |
constructor (num) { | |
this.num = num || 0 | |
this.internal = String(this.num) | |
this.asInt = asInteger(this.internal) | |
} | |
add (target) { | |
target = target || 0 | |
let operands = [this, new Decimal(target)] | |
operands.sort((x, y) => { return x.asInt.exp - y.asInt.exp }) | |
let smallest = operands[0].asInt.exp | |
let biggest = operands[1].asInt.exp | |
let x = Number(format(operands[1].asInt.value, biggest - smallest)) | |
let y = Number(operands[0].asInt.value) | |
let result = String(x + y) | |
return new Decimal(format(result, smallest)) | |
}; | |
sub (target) { | |
return new Decimal(this.add(target * -1)) | |
}; | |
mul (target) { | |
target = new Decimal(target) | |
let result = String(this.asInt.value * target.asInt.value) | |
let exp = this.asInt.exp + target.asInt.exp | |
return new Decimal(format(result, exp)) | |
}; | |
div (target) { | |
let targetT = new Decimal(target) | |
let smallest = Math.min(this.asInt.exp, targetT.asInt.exp) | |
let x = this.mul(Math.pow(10, Math.abs(smallest))) | |
let y = targetT.mul(Math.pow(10, Math.abs(smallest))) | |
return new Decimal(x / y) | |
}; | |
toString () { | |
return this.internal | |
}; | |
roundUp (e) { | |
return new Decimal(Math.ceil(this.mul(Math.pow(10, e)).toNumber())).div(Math.pow(10, e)) | |
}; | |
toNumber () { | |
return Number(this.internal) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment