Since the whole world by now should be aware of the general failure of artificial intelligence, it shouldn’t be very controversial to say that I’ve (mostly) always realized that computers can’t do many things that are very easy for people to do. Forget anything like thinking: the most basic identification of black shapes on a page as alphanumeric characters sometimes fails, and facial recognition seems to be a long way from being anywhere close to reliable.

But reading David Flanagan’s fabulous book “The Ruby Programming Language”, I discovered that computers can’t be trusted to do simple math either. Here’s the direct quote, followed by my simplified explanation.

## Binary Floating-Point and Rounding Errors

Most computer hardware and most computer languages (including Ruby) approximate real numbers using a floating-point representation like Ruby’s Float class. For hardware efficiency, most floating-point representations are binary representations, which can exactly represent fractions like 1/2, 1/4, and 1/1024. Unfortunately, the fractions we use most commonly (especially when performing financial calculations) are 1/10, 1/100, 1/1000, and so on. Binary floating-point representations cannot exactly represent numbers as simple as 0.1.

Float objects have plenty of precision and can approximate 0.1 very well, but the fact that this number cannot be represented exactly leads to problems. Consider the following simple Ruby expression:

`0.4 - 0.3 == 0.1 # Evaluates to false in most implementations`

Because of rounding error, the difference between the approximations of 0.4 and 0.3 is not quite the same as the approximation of 0.1. This problem is not specific to Ruby: C, Java, JavaScript, and all languages that use IEEE-754 floating-point numbers suffer from it as well.

One solution to this problem is to use a decimal representation of real numbers rather than a binary representation. The BigDecimal class from Ruby’s standard library is one such representation. Arithmetic on BigDecimal objects is many times slower than arithmetic on Float values. It is fast enough for typical financial calculations, but not for scientific number crunching. Section 9.3.3 includes a short example of the use of the BigDecimal library.

So, in other words, if you ask what 0.4 – 0.3 is, you get the correct answer. But if you ask if 0.4 – 0.3 is equal to 0.1, you’re told that it’s not the same. And please remember: although Ruby is used in the example, this is not a bug in Ruby, but a generally accepted way for programming languages to work, which has been adopted by the international standards body IEEE.

Add to this the fact that different programming languages disagree what the remainder is when you divide a negative number by a postive number, and you’ll learn that you have to be very careful what you let computers do for you. They could even mess up the one thing that seems perfectly suited to them: basic math.