1. 5

Since 2008, there has been an IEEE 754 standard for decimal floating point values, which fixes this.

The fundamental problem illustrated here is that we are still using binary floating point values to represent (i.e. approximate) decimal values.

1. 6

Yeah, and Python, Julia’s language of choice, has about the world’s only easily accessible implementation of IEEE 754 decimals. Little known fact, Python’s Decimal class is IEEE 754-compliant arithmetic!

1. 8

I was flabbergasted to know that Julia is not Julia’s language of choice.

1. 1

Cool! I didn’t realize that :)

Ecstasy’s decimal types are all built around the IEEE 754 spec as well. Not 100% implemented at this point, though.

1. 1

Is this expected?

>>> Decimal(0.1) + Decimal(0.2)
Decimal('0.3000000000000000166533453694')

1. 18

If you want to create a literal Decimal, pass a string:

>>> Decimal("0.1")
Decimal('0.1')

When you pass a float, you’re losing information before you do any arithmetic:

>>> Decimal(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')

The problem is that 0.1 is not one tenth–it’s some other number very close:

>>> 0.1 .as_integer_ratio()
(3602879701896397, 36028797018963968)

Whereas if you create a Decimal from a string, the Decimal constructor can see the actual digits and represent it correctly:

>>> Decimal("0.1").as_integer_ratio()
(1, 10)

2. 5

I mean it solves this loosely. The places where decimal vs. non-decimal matters - certainly where this seems to come up - are generally places where I would question the use of floating vs fixed point (of any or arbitrary precision).

Base 10 only resolves the multiples of 1/10 that binary can’t represent, but it still can’t represent 1/3, so it seems like base 30 would be better as it can also accurately represent 1/3, 1/6, in addition to 1/2, 1/5, and 1/10. Supporting this non binary format necessarily results in slower operations.

Interestingly to avoid a ~20% reduction in precision the decimal ieee754 actually works in base 1000.

1. 2

“Base 10 only resolves the multiples of 1/10 that binary can’t represent”

That is quite convenient, since humans almost always work in decimals.

I have yet to see a currency that is not expressed in the decimal system.

I have yet to see an order form that does not take its quantities in the decimal system.

In fact, if there’s any type that we do not need, it’s binary floating point, i.e. what programmers strangely call “float” and “double”.

1. 5

I have yet to see a currency that is not expressed in the decimal system. I have yet to see an order form that does not take its quantities in the decimal system.

Yes, which is my point, there are lots of systems for which base 10 is good for humans, but that floating point in any base is inappropriate.

In fact, if there’s any type that we do not need, it’s binary floating point, i.e. what programmers strangely call “float” and “double”.

Every use case for floating point requires speed and accuracy. Every decimal floating point format is significantly more expensive to implement in hardware area, and is necessarily slower than binary floating point. The best case we have for accuracy is ieee754’s packed decimal (or compressed? I can’t recall exactly) which takes a 2.3% hit to precision, but is even slower than the basic decimal form which takes a 20% precision hit.

For real applications the operations being performed typically cannot be exactly represented in base 10 (or 1000) or base 2, so the belief that base 10 is “better” is erroneous. It is only a very small set of cases where a result would be exactly representable in base 10 where this comes up. If the desire is simply “be correct according to my intuition” then a much better format would be base-30, which can also represent 1/(3^n) correctly. But the reality is that the average precision is necessarily lower than base-2 for every non-power of 2 base, and the performance will be slower.

Floating point is intended for scientific and similar operations which means it needs to be as fast as possible, with as much precision as possible.

Places where human decimal behaviour is important are almost universally places where floating point is wrong: people don’t want their bank or order systems doing maths that says x+y==x when y is not zero, which is floating point does. That’s because people are dealing with quantities that generally have a minimum fractional quantity. Once you recognize that, your number format should become an integer count of that minimum quantity.

1. 2

For currencies, you can just use integers, floats are not meant for that anyway. Binary is the most efficient to evaluate on a computer.

1. 3

Yes, for currencies, you can use integers. Who would want to say x * 1.05 when they could say multFixPtDec(x, 105, 2);

To some extent, this is why we use standards like IEEE 754. Some of us remember the bad old days, when every CPU had a different way of dealing with things. 80 bit floats for example. Packed and unpacked decimal types on x86 for example. Yay, let’s have every application solve this in its own unique way!

Or maybe instead, let’s just use the standard IEEE 754 type that was purpose-built to hold decimal values without shitting itself 🤷‍♂️

1. 4

[minor edit: I just saw both my wall of text replies were to u/cpurdy which I didn’t notice. This isn’t meant to have been a series of “target cpurdy” comments]

Yes, for currencies, you can use integers. Who would want to say x * 1.05 when they could say multFixPtDec(x, 105, 2);

I mean, sure if you have a piss poor language that doesn’t let you define a currency quantity it will be annoying. It sounds like a poor language choice if you writing something that is intended to handle money, but more importantly, using floating point for currency is going to cause much bigger problems.

And this has nothing to do with ieee754, that is merely a specific standard detailing how the storage bits for the format work, the issue is fundamental to any floating point format: floating point is not appropriate to anything where use are expecting exact quantities to be maintained (currencies, order quantities, etc) and it will bite you.

Some of us remember the bad old days, when every CPU had a different way of dealing with things. 80 bit floats for example.

So as a heads up assuming you’re complaining about x87’s 80bit floats: those are ieee754 floating point, and are the reason ieee754 exists: every other manufacturer said the ieee754 could not be implemented efficiently until intel went and produced it. The only issue is that being created before finalization of the ieee754 specification it uses an explicit 1-bit which turns out to be a mistake.

Packed and unpacked decimal types on x86 for example.

You’ll be pleased to know ieee754’s decimal variant has packed and unpacked decimal formats - unpacked taking a 20% precision hit but being implementable in software without being catastrophically slow, and packed having only a 2.3% precision hit but being pretty much hardware only (though to be clear as I’ve said elsewhere, still significantly and necessarily slower than binary floating point)

Or maybe instead, let’s just use the standard IEEE 754 type that was purpose-built to hold decimal values without shitting itself 🤷‍♂️

If you are hell bent on using an inappropriate format for your data then maybe decimal is better, but you went wrong when you started using a floating point representation for values that don’t have significant dynamic range where gaining and adding value due to precision limits is not acceptable.

1. 1

[minor edit: I just saw both my wall of text replies were to u/cpurdy which I didn’t notice. This isn’t meant to have been a series of “target cpurdy” comments]

No worries. I’m not feeling targeted.

I mean, sure if you have a piss poor language that doesn’t let you define a currency quantity it will be annoying.

C. C++. Java. JavaScript.

Right there we have 95% of the applications in the world. 🤷‍♂️

How about newer languages with no decimal support? Hmm … Go. Rust.

And this has nothing to do with ieee754

Other than it actually specifies a standard binary format, operations, and defined behaviors thereof for decimal numbers.

So as a heads up assuming you’re complaining about x87’s 80bit floats: those are ieee754 floating point

Yes, there are special carve-outs (e.g. defining “extended precision format”) in IEEE754 to allow 8087 80-bit floats to be legal. That’s not surprising, since Intel was significantly involved in writing the IEEE754 spec.

ieee754’s decimal variant has packed and unpacked decimal formats - unpacked taking a 20% precision hit but being implementable in software without being catastrophically slow, and packed having only a 2.3% precision hit but being pretty much hardware only

I’ve implemented IEEE754 decimal with both declet and binary encoding in the past. Both formats have the same ranges, so there is no “precision hit” or “precision difference”. I’m not sure what you mean by packed vs unpacked; that seems to be a reference to the ancient 8086 instruction set, which supported both packed (nibble) and unpacked (byte) decimal arithmetic. (I used both, in x86 assembly, but probably not in the last 30 years.)

you went wrong when you started using a floating point representation for values that don’t have significant dynamic range where gaining and adding value due to precision limits is not acceptable

I really do not understand this. It is true that IEEE754 floating point is very good large dynamic ranges, but that does not mean that it should only be used for values with a large dynamic range. In fact, quite often IEEE754 is used to deal with values limited between zero and one 🤷‍♂️

1. 5

C. C++. Java. JavaScript.

C++:

struct Currency {
....
operator+, -, ...
}

How about newer languages with no decimal support? Hmm … Go. Rust.

You can also do similar in rust. I did not say “has a built in currency type”.

You can also add one to python, or a variety of other languages. I’m only partially surprised that Java still doesn’t provide support for operator overloading.

And this has nothing to do with ieee754 Other than it actually specifies a standard binary format, operations, and defined behaviors thereof for decimal numbers.

No. It defines the operations on floating point numbers. Which is a specific numeric structure, and as I said one that is inappropriate for the common cases where people are super concerned about handling 1/(10^n) accurately.

I’ve implemented IEEE754 decimal with both declet and binary encoding in the past. Both formats have the same ranges, so there is no “precision hit” or “precision difference”. I’m not sure what you mean by packed vs unpacked; that seems to be a reference to the ancient 8086 instruction set, which supported both packed (nibble) and unpacked (byte) decimal arithmetic.

I had to go back and re-read the spec, I misunderstood the two significand encodings. derp. I assumed your reference to the packed and unpacked was those.

On the plus side, this means that you’re only throwing out 2% of precision for both forms.

I really do not understand this. It is true that IEEE754 floating point is very good large dynamic ranges, but that does not mean that it should only be used for values with a large dynamic range.

No, I mean the kind of things that people care about/need accurate representation over multiples 1/(10^n) do not have dynamic range, fixed/no-point are the correct representation. So optimizing the floating point format for fixed point data, instead of the actual use cases that have widely varying ranges (scientific computation, graphics, etc)

In fact, quite often IEEE754 is used to deal with values limited between zero and one 🤷‍♂️

There is a huge dynamic range between 0 and 1. The entire point of floating point is that all numbers can be represented as a value between [1..Base) with a dynamic range. The point I am making is that the examples where decimal formats is valuable do not need that at all.

2. 2

What is the multiplication supposed to represent? Are you adding a 5% fee? You need to round the value anyway, the customer isn’t going to give you 3.1395 dollars. And what if the fee was 1/6 of the price? Decimals aren’t going to help you there.

1. 2

It never ceases to amaze me how many people really work hard to avoid obvious, documented, standardized solutions to problems when random roll-your-own solutions can be tediously written, incrementally-debugged, and forever-maintained instead.

Help me understand why writing your own decimal support is superior to just using the standard decimal types?

I’m going to go out on a limb here and guess that you don’t write your own “int”, “float”, and “double”. Why is decimal any different?

This whole conversation seems insane to me. But I recognize that maybe I’m the one who is insane, so please explain it to me.

1. 1

No, I’m saying that you don’t need a decimal type at all. If you need to represent an integral value, use an integer. If you want to represent an approximation of a real number, use a float. What else would you want to represent?

1. 3

I would like to have a value that is a decimal value. I am not the only developer who has needed to do this. I have needed it many times in financial services applications. I have needed it many times in ecommerce applications. I have needed it many times in non-financial business applications. This really is not a crazy or rare requirement. Again, why would you want to use a type that provides an approximation of the desired value, when you could just use a type that actually holds the desired value? I’m not talking crazy, am I?

1. 2

What do you mean by “a decimal value”? That’s not an established mathematical term. If you mean any number that can be expressed as m/10ⁿ for some integers m, n, you need to explain precisely why you’d want to use that in a real application. If you mean any number that can be expressed as m/10ⁿ forsome integer m and a fixed integer n, why not just use an integer?

2. 1

My proposal is that we switch to a base 30 floating point format, and that could handle a 1/6th fee :D :D :D

1. 1
3. 2

Being able to say x * 1.05 isn’t a property of the type itself, it’s just language support. If your language supports operator overloading you could use that syntax for fixed point too.

1. 1

Oh, you are using a language with fixed point literals? I have (in the past). I know that C#/VB.NET has its 128-bit non-standard floating point decimal type, so you’re not talking about that. Python has some sort of fixed point decimal support (and also floating point decimal). What language are you referring to?

1. 2

Oh, you are using a language with fixed point literals?

You don’t need to. Strings are a good substitute

For Kotlin it doesn’t really even matter what the left operand is

fun main() {
println("1.05" * 3)
}

operator fun String.times(right_operand: Int): FixedDecimal {
// Do math
return FixedDecimal(); // Return placeholder
}

class FixedDecimal;

https://pl.kotl.in/7FDdqQdSo

1. 1

So your idea is to write your own custom decimal type? And that is somehow better than using an international well-established standard IEEE-754?

I think Kotlin is a nice language, and it’s cool that it allows you to write new classes, but being forced to build your own basic data types (”hey look ma! I invented a character string!”) seems a little crazy to me 🤷‍♂️

1. 2

The idea is that the type represents an underlying standard as well as its defined operations. You don’t need native support for a standard in order to support said standard

Edit:

but being forced to build your own basic data types

I was giving an example about ergonomics and language support rather than using an opaque dependency

1. 4

So, what programming languages are supported? I see a few examples in the demo tabs, python, ruby, typescript, but no definitive list.

1. 5

Python, JavaScript, TypeScript, Ruby and Go.

1. 2

GitHub employee here, but not working on Copilot. Copilot works on lots of languages. It has the best support for Python, JavaScript, TypeScript, Ruby, and Go but it should work well on any somewhat well-known language. For example, it works fairly well on Clojure. For a laugh I tried it on Q and it didn’t seem to really work, though perhaps I needed to work with a larger file.

1. 1

My dev env:

• iTerm2 on macOS, Konsole on Linux, WSL/Windows Terminal on Home PC
• zsh with prezto everywhere
• mosh when I’m not working from office
• tmux for persistent sessions on servers
• VSCode / Neovim for editing (VSCode Remote extensions are very good)
• ripgrep
• git
• docker

Configs:

• Victor Mono or Cascadia Code font
• Pure prompt
• Solarized theme on terminal. I keep switching in text editors
• EditorConfig

Language specific tools:

• Prettier
• Black
1. 2

My personal machine is a Lenovo Y50-70 (upgraded RAM to 16GB and swapped the 5400 RPM HDD for an Evo 860 500GB) running Windows 10 and Ubuntu & connected to a 27-inch BenQ monitor. I’ll build a rig after this laptop breaks down. I am waiting for that day.

I use a MacBook Pro 15-inch 2015 for work.

1. 5

I really wish Firefox would pull a Google and maintain YUM and APT repositories for the current version of Firefox. Various Linux distributions (e.g. Debian and RHEL) only ship Firefox ESR. If you want to run newer versions of Firefox, you have to download a tarball and untar it and plop it somewhere and write your own .desktop files and what-have-you. Not impossible, but not nearly as nice as Chrome, which just hooks into your distro’s package manager on the more common distros.

1. 2

Be careful; you might have people propose Flatpak or AppImage builds of Firefox.

1. 4

Flatpaks exist, and work wonderfully

1. 2

Snaps!

1. 2

I will try to finish coding my tech blog in GatsbyJS. I bought a .dev domain this year but haven’t able to finish it due to one thing or the other.

1. 1

zsh with prezto and pure prompt

~/Documents master*
›

1. 3

I haven’t used VLC for ages, and even back then I preferred MPC-HC (on Windows) or mplayer2 (on Linux). I’m happy mpv user (on Windows and Linux) since its very beginning.

Are there any users who use both mpv and VLC often, and could shed a light what VLC has that mpv cannot provide them?

1. 2

Opening videos straight from the browsers “open with dialogue”. Using subtitles with VLC is more convenient for me. Few years ago I used VLC more when mpv had problems with some matroska containers, don’t know if this is problem anymore.

1. 2

VLC is a bit more Windows-friendly. But on unix, I use gnome-mpv.

1. 1

Do you use vanilla mpv or some kind of front-end with it?

1. 2

No GUI front-ends. I’m mostly keyboard-oriented user, but mpv’s built-in OSC is actually good too, so sometimes I operate with mouse in mpv window.

1. 1