All original content is created in Ukrainian. Not all content has been translated yet. Some posts may only be available in Ukrainian.Learn more

Rounding Decimal Numbers: Mathematical Rules, JavaScript, and Ruby

Post cover: Rounding Decimal Numbers: Mathematical Rules, JavaScript, and Ruby
Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
```html
Rounding is an important operation when working with decimal numbers, as it allows values to be presented in a more convenient form, reducing the number of digits after the decimal point. However, different programming languages may use different approaches to rounding, which can lead to unexpected results in certain scenarios. In this post, we will explore the mathematical rules of rounding and their implementation in JavaScript and Ruby.

Mathematical Rounding

Mathematical rounding is the process of reducing the number of decimal places of a number to make it simpler for use, display, or further calculations. This is especially important in financial, scientific, and engineering computations, where accuracy must be balanced with practicality.
Rounding to the nearest number
This method rounds a number to the nearest whole or decimal number. If the number is exactly halfway between two options (for example, 2.5), it rounds up to the larger number.
Rule: If the fractional part ≥ 0.5, round up. If less — round down.
Example:
2.4 → 2
2.5 → 3
Rounding down
When using this method, all values are rounded down, regardless of the fractional part of the number.
Rule: The number is always rounded down to the smaller whole.
Example:
2.9 → 2
-2.1 → -3
Rounding up
It rounds up, regardless of the fractional part of the number.
Rule: The number is always rounded up to the nearest whole.
Example:
2.1 → 3
-2.9 → -2
Truncating the decimal part
This method simply discards the fractional part, leaving the whole.
Rule: The fractional part of the number is ignored.
Example:
3.9 → 3
-3.9 → -3
We have covered the school curriculum and can move on to JavaScript and Ruby. Let's look at the existing methods, nuances, and pitfalls of each of these programming languages. I focus on these languages because they are my primary work stack.

Rounding in JavaScript

In JavaScript, rounding occurs through the methods Math.round(), Math.floor(), and Math.ceil():
Examples:
  • Math.round(4.73) → 5
  • Math.round(4.76) → 5
  • Math.floor(4.76) → 4 (rounding down)
  • Math.ceil(4.76) → 5 (rounding up)
But first, let's consider the methods toFixed() and toPrecision().
Rounding to a specific number of decimal places (JS)
In JavaScript, to round a number to a specific number of decimal places, the methods toFixed() and toPrecision() are most commonly used.
The toFixed() method allows you to round a number to a specified number of decimal places and returns the result as a string.
num.toFixed(digits);
num: The number to be rounded.
digits: The number of decimal places.
let num = 5.6789;
console.log(num.toFixed(2)); // "5.68"
In the example, the number 5.6789 was rounded to two decimal places, resulting in "5.68". The method always returns a string, so if necessary, it can be converted to a number using parseFloat() or Number().
The toPrecision() method allows rounding a number with a specified total number of digits (including digits before and after the decimal point).
num.toPrecision(precision);
precision: The number of digits.
let num = 5.6789;
console.log(num.toPrecision(3)); // "5.68"
Here, the number 5.6789 is rounded to three digits, resulting in "5.68".
To summarize and compare these methods:
  • toFixed() fixes the number of decimal places.
  • toPrecision() works with all digits of the number, including whole and fractional.
The rounding methods toFixed() and toPrecision() use common mathematical rounding rules — arithmetic rounding. This means they round the number up or down depending on the value of the next digit after the rounding threshold.
Rounding rules:
  1. If the digit after the rounding threshold is less than 5, the number is rounded down (to the smaller side).
  2. If the digit after the rounding threshold is equal to or greater than 5, the number is rounded up (to the larger side).
Examples of .toFixed() with .5
The number 2.5 rounds up to 3, since the digit after the decimal point is 5.
let num = 2.5; 
console.log(num.toFixed(0)); // "3"
Rounding to one decimal place, the number 2.45 becomes 2.5, since the digit after the rounding threshold (4) does not reach 5.
let num = 2.45;
console.log(num.toFixed(1)); // "2.5"
Examples of .toPrecision() with .5
When rounding to two significant digits, the number 1.005 becomes 1.0, since the rounding threshold is at 0, and the next digit is less than 5.
let num = 1.005;
console.log(num.toPrecision(2)); // "1.0"
The number 2.555 rounds to three significant digits, and we get 2.56, since the digit after the rounding threshold is 5.
let num = 2.555;
console.log(num.toPrecision(3)); // "2.56"
JS Features
JavaScript rounds floating-point numbers, and sometimes inaccurate rounding may occur due to the representation of numbers in binary. For example:
let num = 1.005;
console.log(num.toFixed(2)); // "1.00" (expected "1.01")
Here, it was expected that 1.005 would become 1.01, but due to binary arithmetic, the result may be slightly different. To combat these issues, methods such as multiplying the number by 10^n before rounding or using specialized libraries for precise calculations are often employed. You may encounter such solutions to this problem:
let num = 1.005;
let rounded = Math.round(num * 100) / 100;
console.log(rounded); // "1.01"
Now we have reached the practical use of Math methods. To better understand the rounding methods in JavaScript, especially those included in the Math library, let's review the main ones and provide examples of their use.
Math.round()
This method rounds a number to the nearest whole. If the fractional part of the number is greater than or equal to 0.5 — it rounds up, otherwise — down.
Math.round(4.7); // 5
Math.round(4.3); // 4
Math.round(4.5); // 5 (if .5, then up)
Math.round(-1.5); // -1 (negative .5 also rounds up)
Math.floor()
This method always rounds a number down (to the nearest smaller whole number).
Math.floor(4.9); // 4
Math.floor(4.1); // 4
Math.floor(-2.3); // -3 (negative numbers also round down)
Math.ceil()
This method always rounds a number up (to the nearest larger whole number).
Math.ceil(4.1); // 5
Math.ceil(4.9); // 5
Math.ceil(-2.3); // -2 (negative numbers round up)
Math.trunc()
This method truncates the fractional part of a number, returning only the integer part, regardless of whether the fractional part is positive or negative.
Math.trunc(4.9); // 4
Math.trunc(-4.9); // -4
Math.trunc(4.1); // 4
And for convenience, here’s a small cheatsheet in the form of an image:
cheatsheet - округлення в Javascript
cheatsheet - округлення в Javascript
Now let's look at the rounding methods in Ruby. 

Rounding in Ruby

Ruby, like JavaScript, has several methods for rounding numbers. The main methods include round, floor, ceil, and truncate. Let's take a closer look at each of them.
.round
The round method rounds a number to the nearest whole or to a specified number of decimal places. If the fractional part of the number is 0.5 or more, the number rounds up. If less, it rounds down.
2.5.round # => 3
2.49.round # => 2
Rounding to a specified number of decimal places is done by passing an additional parameter:
2.456.round(2)  # => 2.46
.floor
The floor method rounds a number down to the nearest whole, regardless of the value of the fractional part. It is similar to the Math.floor method in JavaScript.
2.9.floor    # => 2
-2.1.floor   # => -3
.ceil
The ceil method, on the contrary, rounds a number up to the nearest whole, regardless of the fractional part. It is analogous to the Math.ceil method in JavaScript.
2.1.ceil     # => 3
-2.9.ceil    # => -2
.truncate
The truncate method discards the fractional part of a number and returns only the integer part. It is similar to the Math.trunc method in JavaScript.
2.9.truncate   # => 2
-2.9.truncate  # => -2
Rounding to a specific number of decimal places (Ruby)
If you need to round a number to a specific number of decimal places, Ruby also allows this using the round method. The parameter in parentheses specifies how many digits to leave after the decimal point.
5.6789.round(2)   # => 5.68
5.6789.round(3)   # => 5.679
Like in JavaScript, rounding in Ruby can also lead to unexpected results due to the use of floating-point numbers. For example, in older versions of Ruby (2.+):
(1.005).round(2)  # => 1.0 (expected 1.01)
Currently, I have ruby 3.2.1 (2023-02-08 revision 31819e82c8) +YJIT [x86_64-darwin23] and I do not see this problem:
(1.005).round(2)
=> 1.01
These nuances with rounding can often come up during technical interviews. So it’s important to work through, understand, and remember them (and keep an eye on updates). We don’t want a trivial rounding error to lead us to problems in a production environment.
cheatsheet - округлення в Ruby
cheatsheet - округлення в Ruby
```

This post doesn't have any additions from the author yet.

What hierarchy does the DOM (Document Object Model) have?
23 Aug 09:22

What hierarchy does the DOM (Document Object Model) have?

meme code
meme code@memecode
How does the artificial intelligence model work?
15 Sep 16:42

How does the artificial intelligence model work?

meme code
meme code@memecode
What does relational mean (in the context of relational databases)?
21 Sep 08:27

What does relational mean (in the context of relational databases)?

meme code
meme code@memecode
What is RDBMS (relational database management system)?
21 Sep 08:56

What is RDBMS (relational database management system)?

meme code
meme code@memecode
What does the ACID principle mean in programming?
24 Sep 20:31

What does the ACID principle mean in programming?

meme code
meme code@memecode
What is Convention over Configuration (in the context of RoR and beyond)?
26 Sep 07:47

What is Convention over Configuration (in the context of RoR and beyond)?

meme code
meme code@memecode
[Fix] Factory not registered: "user" (KeyError) (FactoryBot / Rails 7)
07 Dec 10:46

[Fix] Factory not registered: "user" (KeyError) (FactoryBot / Rails 7)

meme code
meme code@memecode
What is PORO in Ruby?
08 Dec 12:46

What is PORO in Ruby?

meme code
meme code@memecode
What is the difference between spec_helper.rb and rails_helper.rb in RSpec?
08 Dec 13:53

What is the difference between spec_helper.rb and rails_helper.rb in RSpec?

meme code
meme code@memecode
09 Dec 14:50

[Fix] No such file or directory @ rb_sysopen - tmp/pids/server.pid

meme code
meme code@memecode
What you need to know to build a successful freelance career in IT
23 Dec 16:03

What you need to know to build a successful freelance career in IT

meme code
meme code@memecode
Virtual cloud server: what it is and what makes it special
03 Jan 10:58

Virtual cloud server: what it is and what makes it special

meme code
meme code@memecode