Этого вопроса никогда бы не появилось, если бы не двоичная система счисления, которая подливает проблем при умножении дробных чисел на целые в JavaScript.
Пример проблемы умножения:
0.15 * 6
Результат вычисления:
0.8999999999999999
Ещё пример:
1.11 * 7
7.7700000000000005
Очевидно это какой-то бред, потому что (0.15 * 6) = 0.9; а 1.11 * 7 = 7.77
Как работать с подобной неточностью вычислений?
Функция для правильного умножения дробного числа на целое число
Для правильного умножения дробного на целое предлагаю написать свою функцию, которая по сути будет менять знак умножения «*» на знак сложения «+»
function fractional_multiplication (a, b) { var arr = []; function sum (x){ var s = 0; for (i = 0; i < x.length; i++){ s += x[i] } return s }; if (Number.isInteger(a) == true){ arr.length = a; arr.fill(b); return sum(arr) } else {arr.length = b; arr.fill(a); return sum(arr)} }
Как работает эта функция?
Она получает на вход два параметра — два числа. Предполагается, что одно число будет дробным, а другое целым. Функция универсальна и можно подавать числа в любом порядке т. к. проверяется условие — является ли число целым.
В теле функции создаётся переменная arr, которая является пустым массивом. Переменная arr замкнута в функции fractional_multiplication() из-за области видимости. Снаружи к ней нет доступа и она создаётся только в момент вычисления. После вычисления переменная arr удаляется из оперативной памяти.
Переменная arr нужна нам для того, чтобы заполнить массив нужным количеством элементов с дробными числами. Для этого используется «заливка» метод fill() для объектов-прототипов Array. Пример массива arr, [0.15, 0.15, 0.15, 0.15, 0.15, 0.15]. Длина массива будет взята из целого числа.
После создания массива из одинаковых дробных чисел нам нужно будет просуммировать их между собой. С этой задачей справится функция sum(), которая принимает массив из чисел, и возвращает сумму значений элементов.
Результат работы функции
fractional_multiplication(0.15, 6) 0.9
fractional_multiplication(6, 0.15) 0.9
Вывод в консоль:
Альтернативный способ для умножения
Можно производить округления до определённого знака методом toFixed(). Он вернёт строку, которую потом можно преобразовать в число при помощи конструктора Number().
Number((0.15 * 6).toFixed(10)) 0.9 Number((1.11 * 7).toFixed(10)) 7.77
(0.15 * 6).toFixed(10) "0.9000000000" (1.11 * 7).toFixed(10) "7.7700000000"
Информационные ссылки
JavaScript | Как сложить все числа в массиве?
Официальная страница стандарта ECMAScript — https://tc39.es/ecma262/
Официальная страница стандарта ECMAScript — Раздел «20.1 Number Objects» — https://tc39.es/ecma262/#sec-number-objects
Официальная страница стандарта ECMAScript — Раздел «20.1.2.3 Number.isInteger ( number )» — https://tc39.es/ecma262/#sec-number.isinteger
Официальная страница стандарта ECMAScript — Раздел «22.1.3.6 Array.prototype.fill ( value [ , start [ , end ] ] )» — https://tc39.es/ecma262/#sec-array.prototype.fill