So I’ve been watching Numberphile videos on YouTube lately. They did a video about the sum of all the natural numbers being equal to -1/12.

It got me thinking about one of my t-shirts. I have a t-shirt with the statement that “2+2=5 for extremely large values of 2”. This is of course from George Orwell’s book: 1984, however it is just as true as ever. Wait, what? True?

Bear with me. What is 2? 2 is a number. A slightly different 2 would be 2.0. Still 2 though.

So an “extremely large value of 2” would be something like 2.6. It’s still 2. You pronounce it “two point six”, but still “two”.

Two of these added together, 2.6 + 2.6 would then in turn make 5.2, a 5 hurray!

Another way of looking at the 2+2=5 “problem” is with Ruby. Let me make you a script, which will print it out:

a = b = 2.3
puts "#{a.round} + #{b.round} = #{(a+b).round}"

and voilà, there you have it 2 + 2 = 5.

Of course I’m just fooling around. However, there are some quirks to be had from this. Don’t trust numbers! They might tell you that they are something, they are not.

a = 0.1
b = 0.2
puts "#{a} + #{b} = #{a+b}"

The result here is: 0.1 + 0.2 = 0.30000000000000004.

Reason? First lets look at fractions. 1/10 is of course 0.1. 2/10 is 0.2 and so on. We can also do 1/2 which is 0.5. What is 1/3? Well, the closest we can get to it is 0.33... with an infinite string of 3s. However, like with the Numberphile video, if we ever stop putting in 3s, we will be off of the correct result.

In binary 0.3 is the same. 0.3 in binary is 0.10011001100... with an infinite loop of 1100. If we had infinite precision we would be able to correctly write out the number, however, in computers we do not have infinite precision, but are limited to some finite precision, which is why the addition of 0.1 to 0.2 doesn’t yield 0.3, but rather something fairly close.

Let’s try something fun.

puts 0.3 + 10e14 - 10e14

This will actually return 0.25.

Both of these problems can be combated using Ruby’s BigDecimal class, which are not limited by the precision of the computer in the same way. Here we can get the correct result for both problems:

require 'bigdecimal'
a = BigDecimal.new("0.1")
b = BigDecimal.new("0.2")
puts "#{a.to_f} + #{b.to_f} = #{(a+b).to_f}" # => 0.1 + 0.2 = 0.3

puts (BigDecimal.new("0.3") + BigDecimal.new("10e14") - BigDecimal.new("10e14")).to_f # => 0.3