BigFloat

BigInt was a tremendous addition to ECMAScript and as such I believe it is missing it's floating point counterpart. It would behave much the same as BigInt, but for decimals.

const previouslyMaxSafeFloatIThink = 0.9999999999999994

const alsoHuge = BigFloat(0.9999999999999994)
// 0.9999999999999994f

const hugeString = BigFloat("0.9999999999999994")
// 0.9999999999999994f

This could help tremendously for machine learning libraries as many activation functions require high floating point precision, e.g. - sigmoid

And likely many other mathematical applications

BigInt could allow arbitrarily large numbers. It's not possible to allow arbitrarily large decimals. What would be the precision cap of a BigFloat? What if the precision cap isn't large enough? Is that cap configurable? If so, how do operators deal with operands that are both BigFloats, but with different precision caps?

Admittedly my knowledge on the computation of floating points is limited, but I’m surprised the situation is much different than BigInt, such that we can’t create a similarly arbitrarily long float.

That said, I was thinking an implementation similar to the renowned long js library is evidence of a gap in the standard and a potential solution.

There are libraries that allow for BigInt fractions. I believe that fractions are even more useful than floating points. For example, you can have 1/3 represented like this:

class BigFrac {
    numerator = 1n;
    denominator = 3n;

    plus(num){
        /* do math */
    }

    times(num){
        /* do math */
    }
}

Even if you have some ridiculous precision, you can do something like this:

const PI = new BigFrac(
    3141592653589793238462643383279502884197169n,
    1000000000000000000000000000000000000000000n
)

See: GitHub - tc39/proposal-decimal: Built-in decimal datatype in JavaScript

3 Likes

Awesome, this is what I was looking for, thank you!

Perhaps it would have been better worded if I stated that big-ints need an arbitrarily large amount of space to hold the number (depending on how big it is), while decimals sometimes require infinite space, which simply can't happen.

e.g. just think of the decimal representation of 1/3 (in base 10). How would we store that? As @DiriectorDoc suggested, you could just store that as a fraction and not convert it to a decimal, but that has its limits as well. Math.sqrt(2) can't be accurately represented as either a fraction or a decimal. In either case, we'll need to round it somewhere.

In any case, I guess these points are all being discussed in the proposal that @senocular linked to.

i think the problem everybody complains about in javascript is floating-point number that can cause inaccuracies for things like money. That proposal looks similar to Crockfords DEC64 : DEC64: Decimal Floating Point

I would consider an equivalent to:

I recently had an idea; What if there's an Irrational object along with BigFloat.

Irrational literals are denoted by the letter P in math.
It works something like this:

const Pi = 22p / 7p
console.log(Pi) // [object Irrational]

const Tau = 2p * Pi
console.log(Tau) // [object Irrational]

const x = BigFloat(32, Pi), y = BigFloat(32, Tau)
console.log(x, y)
// 3.14159265358979323846264338327950
// 6.28318530717958647692528676655900

const result = x + y
console.log(result)
// 9.4247779607693797153879301498385

mixing different types with either of these objects results in an error

2 * Pi // Error: Cannot mix Irrational and other types

2 * x // Error: Cannot mix BigFloat and other types

Pi + x // Error: Cannot mix Irrational and other types

Irrational can be an object type and BigFloat can be a literal

typeof Pi // object
typeof x // bigfloat

Now there's an interesting scenario:

// What happens when the BigFloats are of different precision?

const x = BigFloat(16,  Pi)
const y = BigFloat(32, Tau)

console.log(x + y) //  ??

// I guess the lower precision one should promote to a higher precision and produce the result with maximum precision.

Infinity and NaN cannot be converted to either of these types so

BigFloat(nPrecision, Infinity) // Error: The number Infinity cannot be converted to a BigFloat

Irrational(NaN) // Error: The number NaN cannot be converted to an Irrational

// BigFloats cannot have Infinity or NaN as precision value
BigFloat(Infinity, x) // Error: The number Infinity cannot be used as precision for BigFloat