Korrekte Gleitkommazahlen

Berechnungen im Bereich der Gleitkommazahlen sind immer zu einem gewissen Grad ungenau. Der Grund dafür ist die interne Darstellung/Speicherung (binär/ begrenzte Bytes) der Zahlen. Jede Sprache muss damit umgehen. Da bildet Ruby natürlich keine Ausnahme.\

Float ist ungenau

Ein Beispiel für eine ungenaue Berechnung mit Float Zahlen:

0.1 + 0.2 # => 0.30000000000000004

Wenn es beispielsweise um Geld geht, kann dieses Problem tatsächlich Geld kosten. Deshalb arbeiten Banken niemals mit Float Zahlen.

BigDecimal ist genau

BigDecimal ist genauso von Numeric abgeleitet, wie Float. Allerdings bietet BigDecimal eine weitaus genauere Gleitkommaarithmetik:

result = BigDecimal.new(0.1, 15) + BigDecimal.new(0.2, 15)
# => #<BigDecimal:21b6848,'0.3E0',9(18)>
result.to_s('F') # => "0.3"

Die Ausgabe von BigDecimal Objekten kann mit dem Argument F im Gleitkommaformat erfolgen:

number = BigDecimal.new(0.1, 5)
number.to_s # => "0.1E0"
number.to_s('F') # => "0.1"

Weitere Notationen sind möglich. So zum Beispiel kann mit einer vorgestellten Zahl die Ausgabe in Blöcke, getrennt durch Leerzeichen, erzwungen werden. Auch positive Zahlen können dementsprechend ausgegeben werden:

number = BigDecimal.new(12.3456789, 15)
number.to_s('3F') # => "12.345 678 9"
number.to_s('+4F') # => "+12.3456 789"

BigDecimal bietet also noch zusätzlich eine rudimentäre Formatierung der Ausgabe.

Integer ist genau

In bestimmten Fällen, macht es Sinn, Werte intern in die kleinstmöglichen Einheit umzuformen und dann Berechnungen in ganzen Zahlen durchzuführen. Lediglich für die Ausgabe müsste dementsprechend wieder umgeformt werden:

number = 20 + 10 # => 30
number / 100.0 # => 0.3

Fazit

In jedem Fall sollte für Berechnungen nie Float verwendet werden. In Ruby sollten Berechnungen von Gleitkommazahlen immer mit BigDecimal durchgeführt werden.