Skip to content

Instantly share code, notes, and snippets.

@mx-rk-quyenl
Last active October 1, 2019 07:58
Show Gist options
  • Save mx-rk-quyenl/c9c8afc1f9894fc3d6558bafb2660490 to your computer and use it in GitHub Desktop.
Save mx-rk-quyenl/c9c8afc1f9894fc3d6558bafb2660490 to your computer and use it in GitHub Desktop.
Javascript decimal, calc
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