kdl icon indicating copy to clipboard operation
kdl copied to clipboard

Non-decimal floats?

Open clarfonthey opened this issue 3 years ago • 6 comments

The official spec doesn't allow for binary, octal, or hexadecimal floats, although there isn't a particular reason why it couldn't. They work exactly the same as decimal floats, just with the prefix at the beginning. For example, 0x1.8 is 0x18 / 0x10 or 1.5.

Note that there is precedent from C++ to include hexadecimal floats, although I don't know of any language that also offers octal and binary floats as well.

My main motivation for this is because I have some data from ICC profiles which I want to represent exactly as given, but with decimal floats there will always be some sort of rounding error. For example, a profile might store a number as 0x0000.9c18, which wouldn't convert precisely into a decimal float.

The biggest change is that instead of e representing an exponent for these floats, the character C++ uses is p to indicate a power of the radix, which I would say makes the most sense. Link to that spec here: https://en.cppreference.com/w/cpp/language/floating_literal

clarfonthey avatar Oct 04 '21 07:10 clarfonthey

I also am not used to GitHub discussions existing, so if this would make more sense over there I can move this.

clarfonthey avatar Oct 04 '21 07:10 clarfonthey

I think it would be better to introduce a fractional type, where both the numerator and denominator can be represented in either binary, octal, hexadecimal or decimal. This would let you cleanly represent any real number that cannot be accurately represented as a floating point number with limited precision.

djmattyg007 avatar Oct 04 '21 12:10 djmattyg007

I think a fraction format would be very cool, but I'm hesitant to prescribe too much implementation detail, and requiring the ability to exactly encode arbitrary fractions feels like step in that direction.

hkolbeck avatar Oct 05 '21 18:10 hkolbeck

My main rationale for not having a Rational/fraction format is exactly that: It adds a lot of implementation complexity for something that is, honestly, probably going to be a niche feature in practice. I'd rather not do that, considering how few languages have built-in support for these.

zkat avatar Oct 05 '21 21:10 zkat

The main reason why I mention non-decimal floats is that they are similar enough to existing floats that implementing them shouldn't be too much of a burden, and they already have accepted syntax as well. Whereas fractions ask a whole load of questions that are hard to answer:

  • If fractions are represented as pairs, then what makes them more special than other data that can be stored as pairs, like complex numbers?
  • If fractions are represented as expressions, then what stops you from adding in addition, subtraction, and multiplication as well?
  • Should fractions be limited to integer ratios, or are floats allowed? What about different bases?
  • Does the denominator have to always be positive, or can it be negative?
  • Is dividing by zero a syntax error? Is it allowed?

Meanwhile the most complicated question for non-decimal floats is how exponents should work, and what character(s) should be used in place of e. And that already is mostly solved as C++ uses p for hex floats and it'd be a horrible mistake IMHO to change that.

There is the question of whether p should also be used by octal and binary floats, but even then, there could also be the option to just allow hex floats like C++. Lot of options there.

clarfonthey avatar Oct 05 '21 22:10 clarfonthey

Implementing non-decimal floats actually would be a burden for most implementations, I'd think. A "parseInt()" or similar function that can take an arbitrary (2-36) base is pretty common, but parseFloat() rarely has an allowed base. (Neither JS nor Python offer this as built-in, for example.) So while binary/octal/hex can today be implemented by just collecting the characters and passing them to a built-in function to get the numeric value, doing the same with non-decimal floats would require writing our own string-to-number functions. (Which aren't remotely hard, but still.)

That said, supporting arbitrary value formats is pretty much exactly what value tags were designed for: (hex)"0.9c18", for example. You get perfect passthru of the value, and then can interpret it into the desired value at the end.

tabatkins avatar Oct 06 '21 17:10 tabatkins

I'm just gonna reject this one as out-of-scope. It's super niche and almost certainly a massive implementation burden.

zkat avatar Nov 28 '23 22:11 zkat