Pular para o conteúdo principal

General: Prevent arbitrary precision arithmetic

Demand

Some simple decimal calculations like 4.6 * 100 may lead in irregularities when dealing with numbers.

Description

During arithmetic operations like addition, subtraction, multiplication, and division, the numbers are manipulated according to the rules defined by the IEEE 754 standard. However, due to the finite precision of the representation, rounding errors may occur, leading to small discrepancies between the expected and actual results of computations.

In simpler terms, the computer operates using powers of 2 (binary-based), so whenever we need to work with a number that cannot be exactly represented in binary (like 0.1, which is a base-10 fraction), it uses an approximation rather than an infinite number and is incapable of presenting the exact correct value.

To prevent it we may use some libraries to prevent the problem. In Javascript and Typescript we have the BigNumbers library (and others). PHP has a built-in library for arbitrary-precision arithmetic called BCMath (Binary Calculator). Wich I reccomend. It provides functions to perform mathematical operations on numbers with arbitrary precision, including addition, subtraction, multiplication, division, and more.

Examples

PHP Sample
1: php > var_dump(floor((10*0.91597) * 1000000)/1000000);
2: float(9.159699)
3: php > var_dump(bcmul(10,0.91597, 6));
4: string(8) "9.159700"
Javascript sample
1: > (Math.floor(10 * (0.91597 * 100 	00)) / 10000).toFixed(4);
2: >- '9.1596'
3: > BigNumber(10).multipliedBy(0.91597).multipliedBy(10000).dividedBy(10000).decimalPlaces(4).toNumber()
4: >- 9.1597

Examples Explanation

In the first line we see a simple operation where we multiply 10 by 0.91597 and should yield to 9.1597 but when not using a precision arithmetic safe library (as shown at line 1) the results are inconsistent (presented in line 2). When using an assistent library (at line 3) the operation results was fixed (as shown at line 4).

When performing floating-point calculations on a computer, the numbers are typically represented in binary format using a fixed number of bits. The IEEE 754 standard is commonly used for floating-point representation, which defines formats for single precision (32 bits) and double precision (64 bits) floating-point numbers.

For example, let's consider the double-precision format, which uses 64 bits to represent a floating-point number. The binary representation consists of three parts: the sign bit, the exponent, and the significand (also known as the mantissa).

When the values 10 and 0.91597 are represented in binary floating-point format, they are approximated to fit into the available number of bits. This approximation may introduce rounding errors due to the limited precision of the representation.

For example, the number 10 in binary floating-point format might be represented as follows:

Sign bit: 0 (positive)

Exponent: 10000000010 (biased exponent, indicating 3 in binary)

Significand: 0100000000000000000000000000000000000000000000000000 (fractional part)

Similarly, the number 0.91597 may be approximated in binary floating-point format as follows:


Sign bit: 0 (positive)

Exponent: 01111111111 (biased exponent, indicating 0 in binary)

Significand: 1101011011001100001010011110101110000101000111101101 (fractional part)


Known equations with simple numbers that will result in arithmetic inaccuracy:

  • 4.6 * 100 = 459.99999999999994
  • 10 * 0.91597 = 9.159699999999999
  • 0.1 + 0.7 = 0.7999999999999999
  • 0.1 + 0.2 = 0.30000000000000004
  • 0.3 - 0.2 = 0.09999999999999998
  • If you know any other equation just like that, please, leave a comment!

    Comentários

    Postagens mais visitadas deste blog

    Demystifying MySQL ALTER TABLE ALGORITHM: INPLACE vs INSTANT vs COPY

      Schema evolution is one of the trickiest aspects of database management. For developers and DBAs, the dreaded ALTER TABLE command often conjures fears of downtime, locks, and performance bottlenecks. But MySQL offers a powerful word! The "ALGORITHM" modifier that determines how schema changes are executed. In this article, we’ll break down the three key algorithms "INPLACE", "INSTANT", and "COPY" to help you understand their trade-offs, performance implications, and even some unconventional ways to use them. Whether you’re optimizing for zero downtime or experimenting with stress testing, this guide will give you practical insights and real-world strategies. IMPORTANT: Check your MySQL version: In MySQL 8.0+, many table changes are instantaneous, and the command modifications presented here are only available in this and later versions. Understanding the ALGORITHM Modifier When you run an ALTER TABLE in MySQL, you can specify the algorithm, lik...

    Article: Preventing Database Gridlock: Recognizing and Resolving Deadlock Scenarios

    Learn how deadlocks occur in database systems, understand their impact on performance, and discover practical techniques for identifying potential deadlock scenarios in your SQL code.

    Collation Confusion: Demystifying VARBINARY vs VARCHAR in Database Design

    Have you ever wondered why your database sorts strings differently than expected, or why a seemingly simple query delivers "quirky" results? If you’ve worked with databases like MySQL, PostgreSQL, or SQL Server, you’ve likely stumbled across the mysterious world of collation and the subtle but critical differences between VARBINARY and VARCHAR data types. In this article I hope to unravel these concepts for you, explore how collation shapes database behavior, and dive into an experimental case study to reveal surprising insights. Whether you’re a developer or a database engineer, this deep dive will equip you with practical knowledge to avoid common pitfalls and optimize your database designs. Let’s get started! What Is Collation and Why Does It Matter? Collation refers to the set of rules a database uses to compare and sort character strings. It governs how strings are ordered (e.g., is “Apple” less than “apple”?), how accents are treated (e.g., does “é” equal “e”?), and eve...