Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@axetroy
Created January 27, 2021 01:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save axetroy/4aa6175198f61a40e1fd417f049dcfec to your computer and use it in GitHub Desktop.
Save axetroy/4aa6175198f61a40e1fd417f049dcfec to your computer and use it in GitHub Desktop.
Big Float
type Numeric = number | string | BigInt
function getType(o: unknown): string {
const matcher = Object.prototype.toString.call(o).match(/\s(\w+)/)
if (!matcher) {
return ''
}
return matcher[1]
}
class BigFloat {
private base!: BigInt
private digit = 0
constructor(base: Numeric, d?: number) {
const [int, digit] = BigFloat.number2BigInt(base)
this.base = int
if (d !== undefined) {
this.digit = d
} else {
this.digit = digit
}
}
public plus(n: Numeric): BigFloat {
const [int, digit] = BigFloat.number2BigInt(n)
const maxDigit = Math.max(this.digit, digit)
const base = BigInt(this.base.toString() + '0'.repeat(maxDigit - this.digit))
const target = BigInt(int.toString() + '0'.repeat(maxDigit - digit))
return new BigFloat(base + target, maxDigit)
}
public times(n: Numeric): BigFloat {
const [int, digit] = BigFloat.number2BigInt(n)
const maxDigit = Math.max(this.digit, digit)
const base = BigInt(this.base.toString() + '0'.repeat(maxDigit - this.digit))
const target = BigInt(int.toString() + '0'.repeat(maxDigit - digit))
return new BigFloat(base * target, Math.pow(maxDigit, 2))
}
public toString(): string {
const str = this.base.toString()
const dotPosition = str.length - this.digit
let result = str.slice(0, dotPosition).concat('.').concat(str.slice(dotPosition))
if (dotPosition === 0) {
result = '0' + result
}
if (this.digit > 0) {
result = result.replace(/0+$/, '')
result = result.replace(/\.$/, '')
}
return result
}
private static number2BigInt(num: unknown): [BigInt, number] {
const type = getType(num)
if (type === 'BigInt') {
return [num as BigInt, 0]
} else if (type === 'Number') {
const numString = (num as number).toString()
// float
const dotIndex = numString.indexOf('.')
// if float64
if (dotIndex >= 0) {
const digit = numString.length - dotIndex - 1
const numArr = numString.split('')
const intString = numArr
.slice(0, dotIndex)
.concat(numArr.slice(dotIndex + 1))
.join('')
.replace(/^0+/, '')
return [BigInt(intString), digit]
} else {
// if int
return [BigInt(num), 0]
}
} else if (type === 'String') {
const numString = num as string
if (/^\d+(\.\d+)?$/.test(numString)) {
if (/^\d+$/.test(numString)) {
return [BigInt(num), 0]
} else {
// if float
const dotIndex = numString.indexOf('.')
const digit = numString.length - dotIndex - 1
const numArr = numString.split('')
const intString = numArr
.slice(0, dotIndex)
.concat(numArr.slice(dotIndex + 1))
.join('')
.replace(/^0+/, '')
return [BigInt(intString), digit]
}
} else {
throw new TypeError(`invalid number '${num}'`)
}
} else {
throw new TypeError(`invalid number '${num}'`)
}
}
}
console.log(new BigFloat(0.1).plus(0.2333).toString())
console.log(new BigFloat(0.123456789).plus(0.987654321).toString())
console.log(new BigFloat('123.93323123123123123123990844').plus('0.123409212333333123123').toString())
console.log(new BigFloat('0.123').times('0.321').toString())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment