Your language isnβt broken, itβs doing floating point math. Computers can only
natively store integers, so they need some way of representing decimal numbers.
This representation is not perfectly accurate. This is why, more often than not,
0.1 + 0.2 != 0.3
.
Itβs actually rather interesting. When you have a base10 system (like ours), it can only express fractions that use a prime factor of the base. The prime factors of 10 are 2 and 5. So 1/2, 1/4, 1/5, 1/8, and 1/10 can all be expressed cleanly because the denominators all use prime factors of 10. In contrast, 1/3, 1/6, and 1/7 are all repeating decimals because their denominators use a prime factor of 3 or 7.
In binary (or base2), the only prime factor is 2, so you can only cleanly express fractions whose denominator has only 2 as a prime factor. In binary, 1/2, 1/4, 1/8 would all be expressed cleanly as decimals, while 1/5 or 1/10 would be repeating decimals. So 0.1 and 0.2 (1/10 and 1/5), while clean decimals in a base10 system, are repeating decimals in the base2 system the computer uses. When you perform math on these repeating decimals, you end up with leftovers which carry over when you convert the computerβs base2 (binary) number into a more humanreadable base10 representation.
Below are some examples of sending .1 + .2
to standard output in a variety of
languages.
Read more:
Language  Code  Result 

π ABAP 

π ABAP 
and

and

π APL 

π APL 


π Ada 

π Ada 


π AutoHotkey 

π AutoHotkey 


π C 

π C 


π C# 

π C# 
and
and

and
and

C# has support for 128bit decimal numbers, with 2829 significant digits
of precision. Their range, however, is smaller than that of both the single and
double precision floating point types. Decimal literals are denoted with the 

π C++ 

π C++ 


π Clojure 

π Clojure 


Clojure supports arbitrary precision and ratios. 

π ColdFusion 

π ColdFusion 


π Common Lisp 

π Common Lisp 
and
and
and

and
and
and

CLβs spec doesnβt actually even require radix2 floats (let alone specifically 32bit singles and 64bit doubles), but the highperformance implementations all seem to use IEEE floats with the usual sizes. This was tested on SBCL and ECL in particular. 

π Crystal 

π Crystal 
and

and

π D 

π D 


π Dart 

π Dart 


π Delphi XE5 

π Delphi XE5 


π Elixir 

π Elixir 


π Elm 

π Elm 


π Elvish 

π Elvish 


Elvish uses Goβs 

π Emacs Lisp 

π Emacs Lisp 


π Erlang 

π Erlang 


π FORTRAN 

π FORTRAN 


π GHC (Haskell) 

π GHC (Haskell) 
and
and

and
and

If you need real numbers, packages like exactreal give you the correct answer. 

π GNU Octave 

π GNU Octave 
and
and
and
and
and

and
and
and
and
and

π Gforth 

π Gforth 


π Go 

π Go 


Go numeric constants have arbitrary precision. 

π Groovy 

π Groovy 


Literal decimal values in Groovy are instances of java.math.BigDecimal. 

π Hugs (Haskell) 

π Hugs (Haskell) 


π Io 

π Io 


π Java 

π Java 
and

and

Java has builtin support for arbitraryprecision numbers using the BigDecimal class. 

π JavaScript 

π JavaScript 


The decimal.js library provides an arbitraryprecision Decimal type for JavaScript. 

π Julia 

π Julia 


Julia has builtin rational numbers support and also a builtin
arbitraryprecision BigFloat data type. To get the math right, 

π K (Kona) 

π K (Kona) 


π Kotlin 

π Kotlin 
and

and

π Lua 

π Lua 
and

and

π MATLAB 

π MATLAB 
and

and

π Mathematica 

π Mathematica 


Mathematica has a fairly thorough internal mechanism for dealing with numerical precision and supports arbitrary precision. 

π MySQL 

π MySQL 


π Nim 

π Nim 


π OCaml 

π OCaml 


π ObjectiveC 

π ObjectiveC 


π PHP 

π PHP 
and
and

and
and

PHP 

π Perl 

π Perl 
and
and

and
and

The addition of float primitives only appears to print correctly because not all of the 17 digits are printed by default. The core Math::BigFloat allows true arbitrary precision floating point operations by never using numeric primitives. 

π PicoLisp 

π PicoLisp 


You must load file βfrac.min.lβ. 

π PostgreSQL 

π PostgreSQL 


π Powershell 

π Powershell 


π Prolog (SWIProlog) 

π Prolog (SWIProlog) 


π Pyret 

π Pyret 
and

and

Pyret has builtin support for both rational numbers and floating points.
Numbers written normally are assumed to be exact. In contrast, RoughNums are
represented by floating points, and are written prefixed with a 

π Python 2 

π Python 2 
and
and
and

and
and
and

Python 2βs 

π Python 3 

π Python 3 
and
and
and

and
and
and

Python (both 2 and 3) supports decimal arithmetic with the decimal module, and true rational numbers with the fractions module. 

π R 

π R 
and

and

π Racket (PLT Scheme) 

π Racket (PLT Scheme) 
and

and

π Raku 

π Raku 
and
and
and

and
and
and

Raku uses rationals by default, so 

π Ruby 

π Ruby 
and

and

Ruby supports rational numbers in syntax with version 2.1 and newer directly. For older versions use Rational. Ruby also has a library specifically for decimals: BigDecimal. 

π Rust 

π Rust 


Rust has rational number support from the num crate. 

π SageMath 

π SageMath 
and
and
and

and
and
and

SageMath supports various fields for arithmetic: Arbitrary Precision Real Numbers, RealDoubleField, Ball Arithmetic, Rational Numbers, etc. 

π Scala 

π Scala 
and
and

and
and

π Smalltalk 

π Smalltalk 


π Swift 

π Swift 
and

and

Swift supports decimal arithmetic with the Foundation module. 

π TCL 

π TCL 


π Turbo Pascal 7.0 

π Turbo Pascal 7.0 


π Vala 

π Vala 


π Visual Basic 6 

π Visual Basic 6 


Appending the identifier type character 

π WebAssembly (WAST) 

π WebAssembly (WAST) 
and

and

See demo. 

π awk 

π awk 


π bc 

π bc 


π dc 

π dc 


π zsh 

π zsh 

