You Probably Don't Know Of These 2 Math Methods in JavaScript: fround() and imul()
Tags: javascript, beginners, tutorial, learning
Published: 2024-02-27 14:39:59

## Table of contents
- [Introduction](#Introduction)
- [What is `Math.fround()`?](#What_is_Mathfround())
    - [Examples of `fround()`](#Examples_of_fround())
    - [Practical applications of `fround()`](#Practical_applications_of_fround())

- [What is `Math.imul()`?](#What_is_Mathimul())
    - [Examples of `imul()`](#Examples_of_imul())
    - [Practical application of `imul()`](#Practical_application_of_imul())


## Introduction<a name="Introduction"></a><a name="Introduction"></a>

When JavaScript was first released to the public in 1995 in the Netscape Navigator 2.0 browser, no one could've ever imagined the sheer level of complexity the language would tackle in the coming years.

Fast-forwards 25 years, JavaScript is being used for all different kinds of things, from gaming, to servers, to mathematical algorithms, to I/O, to system applications, to embedded systems (such as in Raspberry PI) — _it's just everywhere!_

In this regard, there has been a lot that the ECMA International community — the one behind churning all the nice bells and whistles into JavaScript — has come to realize over the years.

For example, back then, there were no features in the language to efficiently handle [asynchronous programming](https://www.codeguage.com/courses/advanced-js/promises-introduction). Then the world eventually got [promises](https://www.codeguage.com/courses/advanced-js/promises-introduction) in ES6.

Similarly, JavaScript natively lacked an efficient way to organize code into different files — known as _modules_ — for a very very long time. But, thanks to ES6 again, the world got [ECMAScript modules](https://www.codeguage.com/courses/advanced-js/modules-introduction), with the `import` and `export` constructs to power modular programming natively in this beautiful scripting language.

Now when we talk about the `Math` object, few might know that it too got a couple of advancements over these years, purely based on the sheer extent of complexity being handled by JavaScript.

In this article, we'll talk about two methods added to the `Math` object in JavaScript with the inception of ES6, following from some advanced usage of the language in different contexts.

These methods are **`fround()`**, for converting numbers to 32-bit floating-point numbers' precision, and **`imul()`**, for efficiently performing integer multiplication in a system optimized for efficiently running JavaScript.

Even if you're not going to use these methods in production (which especially holds for `imul()`), it's still good to know of them in order to understand a couple of concepts in programming in general, and solidifying your grasp of one of the most surprising languages of all time _(that is JavaScript!)_.

-----

## What is `Math.fround()`?<a name="What_is_Mathfround()"></a><a name="What_is_Mathfround()"></a>

Let's start off with the **`Math.fround()`** method which does have practical applications in userland code (i.e. code that we developers write).

**`Math.fround()`** takes a number and rounds it to the precision of a **single-precision** floating-point number.

The whole crux of understanding `Math.fround()` lies in understanding the single-precision floating-point format, common to all modern programming languages, including JavaScript.

_So do you know about this format?_ Well, let's see what it is very quickly.

Recall that JavaScript stores every single number, be that an integral number or a number with a fractional part, internally as a floating-point number in the **IEEE-754 double-precision floating-point format**.

_"Woah, that's a long name!"_ you say. It indeed is. Let's dissect it.

**_IEEE_** stands for **_[Institute of Electrical and Electronics Engineers](https://en.wikipedia.org/wiki/Institute_of_Electrical_and_Electronics_Engineers)_**; in simple words, it represents a body that looks after standardizing disciplines and implementations of digital systems.

The number 754 represents an identifier for the floating-point numbers standard.

**💡 Notice**: IEEE — or better to say, IEEE SA (IEEE Standard Association) looks after multiple standards so they obviously need a way to distinguish between them.

The term _'double-precision'_ refers to the second of the two formats for storing floating-point numbers in memory, that is, in 64 bits. (The term _'double'_ specifically comes from the fact that this format spans double the memory of the single-precision format.)


> #### Getting into the IEEE-754 double- and single-precision formats<a name=""></a>
> 
> In the IEEE-754 double-precision format, a number occupies 64 bits in memory, and is represented in terms of [scientific notation](https://www.codeguage.com/courses/js/numbers-basics#Scientific_notation): with a **_mantissa_**, an **_exponent_**, in addition to a **_sign_**.
> 
> Here's the distribution of these bits:
> 
> - 52 bits for the mantissa
> - 11 bits for the exponent
> - 1 bit for the sign
> 
> 
> We won't go into the details of how these work because there's quite a lot to cover, all of which is essentially out of the scope of this article.
> 
> What's important for now, for the `Math.fround()` method, is that a double-precision floating-point number has a precision of **53 bits** (the additional 1 bit is implicit in the format).
> 
> This isn't the case for a single-precision number. In particular, in the IEEE-754 single-precision format, a number occupies 32 bits in memory, and is expressed again in terms of scientific notation.
> 
> The distributions of bits in this format is as follows:
> 
> - 23 bits for the mantissa
> - 8 bits for the exponent
> - 1 bit for the sign
> 
> 
> Notice how the single-precision format leads to numbers with much less precision than that of the double-precision format. To be square, a single-precision number has a precision of **23 bits**.

Alright, this knowledge of both the double-precision and single-precision floating-point format has set us up to be able to explore the intuition behind `fround()`, so let's get right to it.

`fround()` converts a number in JavaScript to the precision of a single-precision floating-point number.

It's extremely important to note that the method does NOT return a single-precision number in JavaScript, so to speak; it returns back a number in the same double-precision format used all over JavaScript.

It's just that this returned double-precision number doesn't use its 53-bit precision to the full; it rather uses only 23 bits of precision (essentially, the rest of the bits just don't matter).

If you notice, this is indicated in the name of the method as well: it's _'fround'_ which means to merely _'round'_ a given number to the precision of the single-precision floating-point format.

In that sense, `fround()` has similarities to the [`Math.round()`](https://www.codeguage.com/courses/js/numbers-math-object#Rounding_to_the_nearest_integer) method.

**💡 Notice**: If you're curious about the meaning of the letter _'f'_ in fround, know that it comes from the word _'float'_ commonly used in programming languages to represent the single-precision floating-point number type, `float`. A similar type, `double`, represents the double-precision floating-point format.

### Examples of `fround()`<a name="Examples_of_fround()"></a><a name="Examples_of_fround()"></a>

Let's consider a couple of examples of using `fround()`.

In the following snippet, we demonstrate one of the most popular arithmetic expressions in JavaScript, i.e. `0.1 + 0.2`, in a typical way and then by rounding both numbers using `Math.fround()`:

Output:
```javascript
0.1 + 0.2 // 0.30000000000000004
Math.fround(0.1) + Math.fround(0.2) // 0.30000000447034836
```

Notice how clear-cut discrepancy exists between the both numbers. In particular, the return value of `0.1 + 0.2` is much more precise (that is, much more closer to `0.3`) than `Math.fround(0.1) + Math.fround(0.2)`.

Let's consider another example, this time operating with the [`Math.PI`](https://www.codeguage.com/courses/js/numbers-math-object#Useful_mathematical_constants) constant:

Output:
```javascript
Math.PI * 2 // 6.283185307179586
Math.fround(Math.PI) * 2 // 6.2831854820251465
```

Once again, there is a very noticeable difference between the outcomes in both cases.

This testifies to the fact that floating-point arithmetic with the single-precision format can yield quite different results compared to when using the double-precision format.

So now that we know what `fround()` exactly does and how it works, it's time to consider its practical usage in applications.

### Practical applications of `fround()`<a name="Practical_applications_of_fround()"></a><a name="Practical_applications_of_fround()"></a>

Starting off with the good news, you won't almost ever be needing `fround()` in your JavaScript applications, even some of the most complex ones.

It's only when you know that you _definitely_ need to work with the precision of a single-precision floating-point number that `fround()` makes sense.

For example, let's say you have a JavaScript program that reads a binary file containing a sequence of 32-bit single-precision floats and now want to process those integers in some way and then write the result back to the binary file in the respective locations.

Of course, you can do without using `Math.fround()` for processing these 32-bit floats. However, if producing consistent results is a requirement of the program, then you might want to re-consider this approach. Processing numbers using the double-precision format can produce results that are off by precision when compared to similar results obtained by processing single-precision numbers.

_This isn't rocket science. It's pure logic._ High-precision numbers when coerced to low-precision numbers might put the balance off than if we were using low-precision numbers from the get go.

Coming back to the example presented, if the JavaScript program reading the binary file requires consistency with the single-precision floating-point format, then we must leverage the `Math.fround()` method before performing any operation on the obtained numbers.

_As simple as that._

As another example, let's say we're in a competitive programming setting and a particular question asks us to provide answers in the precision of the well-known `float` type in programming. As stated above, the `float` type is the analogue of 32-bit single-precision floats in programming languages.

Now, if we wish to solve the question using JavaScript (although real competitive programmers swear by C, C++ and Java, only), we'd clearly need to use the `Math.fround()` method, again before every single, concerned arithmetic operation that relates to the final answer.

_"Why?"_ you ask. Well, because we want to make sure that our program doesn't produce any precision inconsistencies with the accepted answer.

**💡 Notice**: This example of a competitive programming problem is purely for the sake of explanation; usually, questions in competitive programming that rely on floating-point answers allow for a _range_ of acceptable answers.

In short, while `fround()` isn't going to be one of the most used methods of the `Math` object for you in your JavaScript programs, it does have some important applications as specified here.

It should be in the arsenal of a real-pro JavaScript developer, especially the one who's going to deal with a lot of intensely mathematical and low-level algorithms.

-----

## What is `Math.imul()`?<a name="What_is_Mathimul()"></a><a name="What_is_Mathimul()"></a>

The second usually-unknown method of `Math` is **`imul()`**.

Before we begin, the good news with `imul()` is that you never need it in your code. _Yes, that's right — never!_ _Simple._

`imul()` is a helpful feature exclusively meant for JavaScript code produced by computer programs themselves. The typical example of this is [Emscripten](https://www.codeguage.com/blog/javascript-math-fround-and-imul), a project to map low-level C/C++ code to asm.js, a strict subset of JavaScript.

_So then why worry about understanding `Math.imul()`?_ Two reasons:

- You'll understand some general programming concepts.
- You'll get to appreciate one of the ways in which JavaScript engines approach optimizing programs specifically meant to be run as efficiently as possible.


_So what is `Math.imul()`?_

**`Math.imul()`** is used to multiply two given numbers together based on the semantics of **multiplying 32-bit signed integers**, as in languages such as C.

When we multiply two numbers in JavaScript, for instance `5` and `10`, the multiplication operation internally resorts to floating-point multiplication, in this case giving `50`.

32-bit integer multiplication is quite different from this.

In particular, if the product of the multiplication is beyond 232, it's reduced modulo 232 and then normalized based on its sign. In other words, it's always made sure that the result of the multiplication is within the range of a 32-bit integer.

**💡 Notice**: The integers we're talking about here are all signed 32-bit integers.

### Examples of `imul()`<a name="Examples_of_imul()"></a><a name="Examples_of_imul()"></a>

Shown below are a couple of `Math.imul()` calls on a bunch of numbers.

When the outcome of a multiplication operation is within the range of a signed 32-bit integer, the return value of `Math.imul()` is the same as the multiplication operator (`*`) in JavaScript, as follows:

Output:
```javascript
Math.imul(2, 3) // 6
Math.imul(2, -1) // -2
Math.imul(105, 100) // 10500
Math.imul(-2, -9999) // 19998
```

But when the outcome exceeds this range, `Math.imul()` reduces the result modulo 232 and then normalizes the final value (that is, making it negative in case it is greater than or equal to 231).

This is illustrated below:

Output:
```javascript
Math.imul(1024, 2097152) // -2147483648
1024 * 2097152 // 2147483648
```

Multiplying `1024` with `2097152` gives 231. After reducing 231 modulo 232 and the normalizing the result, we get -231. This describes the difference between the `Math.imul()` and the `*` operator calls.

_But why would we ever want to convert numbers to 32-bit integers before multiplying them in JavaScript?_

Let's find out.

### Practical application of `imul()`<a name="Practical_application_of_imul()"></a><a name="Practical_application_of_imul()"></a>

_Why would we ever want to use `Math.imul()` in JavaScript?_

As stated before, `Math.imul()` isn't meant to be used by userland code. In fact, if we go on and use it, we might get a performance hit by virtue of the conversion of each given (double-precision) number to an integer prior to the multiplication, and then conversion back to a double-precision number.

`Math.imul()` is a feature introduced _exclusively_ for enforcing **optimizations in JavaScript** programs produced by other programs (which are out of the scope of this article).

Taking the example of Emscripten, when it converts a C/C++ program into JavaScript, the goal of the conversion is to run the resultant JavaScript code extremely efficiently.

**💡 Notice**: This goal makes sense because C and C++ are both statically-typed languages and, likewise, a ton of knowledge is already known about the flow of execution in the program and how variables interact with one another, what given operators mean, and so on. All of this knowledge can be in turn used to hint JavaScript engines to run the final JavaScript program superbly efficiently, paying off the ultimate power of C/C++ code.

Obviously, the converted code when run in JavaScript is much slower than C/C++ counterpart, but if we compare this code to a normal JavaScript program we'd typically write, it's much faster.

In this respect, one hint that JavaScript engines use to understand the nature of the multiplication operation is `Math.imul()`.

`Math.imul()` in such optimized JavaScript code translates to quick low-level operations when compiled by an intelligent JavaScript engine, performing the multiplication of two given integers based on integer arithmetic.

This notion can be easily confirmed by going through the source code of Emscripten. Particularly, in the [`em_math.h`](https://github.com/emscripten-core/emscripten/blob/e0c3ce6d2b3f121abab481e6e79a1a60e2fcd18b/system/include/emscripten/em_math.h#L33) file, which contains C code, head over to line 33, where the `Math.imul()` method is mentioned along with some useful information.

Here's the useful comment that precedes the series of methods containing `Math.imul()` in `em_math.h`:

> The following operations [which include `Math.imul()`] have very fast WebAssembly opcodes.

If we inspect the file further, we see that it says that `Math.imul()` gets converted to the opcodes `i32.mul` and `i64.mul`. These codes can be seen in [this WebAssembly Opcode Table](https://pengowray.github.io/wasm-ops/).

And that's essentially it about `Math.imul()`.

It's a feature exclusively meant for optimizing JavaScript engines for code that is typically not ever written by a human developer. It's good to know about it but not really good or any sensible to use it in userland code.

-----