Простые правила округления в javascript. Изучаем методы и применяем на практике
В этой статье подробно рассмотрим числа, математические операторы, способы преобразования числа в строку и наоборот, а также много других важных моментов.
Функция isFiniteФункция isFinite позволяет проверить, является ли аргумент конечным числом.
В качестве ответа данная функция возвращает false , если аргумент является Infinity , -Infinity , NaN или будет быть приведён к одному из этих специальных числовых значений. В противном случае данная функция вернёт значение true .
IsFinite(73); // true isFinite(-1/0); // false isFinite(Infinity); // false isFinite(NaN); // false isFinite("Текст"); // false
Кроме глобальной функции isFinite в JavaScript имеется ещё метод Number.isFinite . Он в отличие от isFinite не осуществляет принудительное приведения аргумента к числу.
IsFinite("73"); // true Number.isFinite("73"); // false
Функция isNaNФункция isNaN предназначена для определения того, является ли аргумент числом или может ли быть преобразован к нему. Если это так, то функция isNaN возвращает false. В противном случае она возвращает true.
IsNaN(NaN); //true isNaN("25px"); //true, т.к. 20px - это не число isNaN(25.5); //false isNaN("25.5"); //false isNaN(" "); //false, т.к. пробел или неcколько пробелов преобразуется к 0 isNaN(null); //false, т.к. значение null преобразуется к 0 isNaN(true); //false, т.к. значение true преобразуется к 1 isNaN(false); //false, т.к. значение false преобразуется к 0
Если это действие нужно выполнить без приведения типа, то используйте метод Number.isNaN . Данный метод был введён в язык, начиная с ECMAScript 6.
Как явно преобразовать строку в число?Явно привести строку в число можно посредством следующих способов:
1. Использовать унарный оператор + , который необходимо поместить перед значением.
+"7.35"; // 7.35 +"текст"; // NaN
Этот способ пренебрегает пробелами в начале и конце строки, а также \n (переводом строки).
+" 7.35 "; //7.35 +"7.35 \n "; //7.35
Используя данный способ необходимо обратить внимание на то, что пустая строка или строка, состоящая из пробелов и \n , переводится в число 0. Кроме этого она также преобразует тип данных null и логические значения к числу.
Null; //0 +true; //1 +false; //0 +" "; //0
2. Функция parseInt . Данная функция предназначена для преобразования аргумента в целое число . В отличие от использования унарного оператора + , данный метод позволяет преобразовать строку в число, в которой не все символы являются цифровыми . Начинает она преобразовывать строку, начиная с первого символа. И как только она встречает символ, не являющийся цифровым, данная функция останавливает свою работу и возвращает полученное число.
ParseInt("18px"); //18 parseInt("33.3%"); //33
Данная функция может работать с разными системами счисления (двоичной, восьмеричной, десятичной, шестнадцатеричной). Указание основание системы счисления осуществляется посредством 2 аргумента.
ParseInt("18px", 10); //18 parseInt("33.3%", 10); //33 parseInt("101",2); //5 parseInt("B5",16); //181
Кроме функции parseInt в JavaScript имеется метод Number.parseInt . Данный метод ничем не отличается от функции parseInt и был введён в JavaScript со спецификацией ECMASCRIPT 2015 (6).
3. Функция parseFloat . Функция parseFloat аналогична parseInt , за исключением того что позволяет выполнить преобразование аргумента в дробное число.
ParseFloat("33.3%"); //33.3
Кроме этого функция parseFloat в отличие от parseInt не имеет 2 аргумента, и следовательно она всегда пытается рассмотреть строку как число в десятичной системе счисления.
ParseFloat("3.14"); parseFloat("314e-2"); parseFloat("0.0314E+2");
Кроме функции parseFloat в JavaScript имеется метод Number.parseFloat . Данный метод ничем не отличается от функции parseFloat и был введён в JavaScript со спецификацией ECMASCRIPT 2015 (6).
Преобразование числа в строкуПревратить число в строку можно с помощью метода toString .
(12.8).toString(); //"12.8"
Метод toString позволяет также указать основание системы счисления с учётом которой необходимо явно привести число к строке:
(255).toString(16); //"ff"
Как проверить является ли переменная числомОпределить является ли значение переменной числом можно используя один из следующих способов:
1. С использованием функций isNaN и isFinite:
// myVar - переменная if (!isNaN(parseFloat(myVar)) && isFinite(parseFloat(myVar))) { //myVar - это число или может быть приведено к нему };
В виде функции:
// функция function isNumeric(value) { return !isNaN(parseFloat(value)) && isFinite(parseFloat(value)); } // использование var myVar = "12px"; console.log(isNumeric(myVar)); //true
Этот способ позволяет определить является ли указанное значение числом или может быть приведено к нему. Данный вариант не считает числом пустую строку, строку из пробелов, значение null , Infinity , -Infinity , true и false .
2. С использованием оператора typeof и функций isFinite, isNaN:
// функция которая проверяет является ли значение числом function isNumber(value) { return typeof value === "number" && isFinite(value) && !isNaN(value); }; // использование функции isNumber isNumber(18); //true // использование функций для проверки текстовых значений isNumber(parseFloat("")); //false isNumber(parseFloat("Infinity")); //false isNumber(parseFloat("12px")); //true
Эта функция определяет имеет ли указанное значение тип Number, а также не принадлежит ли оно к одному из специальных значений Infinity, -Infinity и NaN. Эсли это так, то данная функция возвращает значение true.
3. С помощью метода ECMAScript 6 Number.isInteger(value) . Данный метод позволяет определить, является ли указанное значение целым числом.
Number.isInteger("20"); //false, т.к. данный метод не выполняет перевод строки в число Number.isInteger(20); //true, т.к. данное значение является числом
Чётные и нечётные числаПроверить является ли число чётным или нечётным можно посредством следующих функций:
// Функция для проверки числа на чётность function isEven(n) { return n % 2 == 0; } // Функция для проверки числа на нечётность function isOdd(n) { return Math.abs(n % 2) == 1; }
Но перед тем как проводить такую проверку желательно убедиться что указанное значение является числом:
Value = 20; if (Number.isInteger(value)) { if (isEven(value)) { console.log("Число " + value.toString() + " - чётное"); } }
Простые числа в JavascriptРассмотрим пример в котором выведем с помощью Javascript простые числа от 2 до 100.
// Функция, которая проверяет является ли число простым function isPrime(value) { if (isNaN(value) || !isFinite(value) || value%1 || value < 2) return false; var max=Math.floor(Math.sqrt(value)); for (var i = 2; i< = max; i++) { if (value%i==0) { return false; } } return true; } // создать массив, который будет содержать простые числа от 2 до 100 var primaryNumber = ; for (var i = 2; i (больше), < (меньше), >= (больше или равно), 3); //false console.log(5>=3); //true
При сравнении чисел с дробной частью необходимо учитывать погрешности, которые могут возникать во время этих вычислений.
Например, в JavaScript сумма чисел (0.2 + 0.4) не равна 0.6:
Console.log((0.2+0.4)==0.6); //false
Погрешности происходят потому что все вычисления компьютер или другое электронное устройство производит в 2 системе счисления. Т.е. перед тем как выполнить какие-то действия компьютер сначала должен преобразовать представленные в выражении числа в 2 систему счисления. Но, не любое дробное десятичное число можно представить в 2 системе счисления точно.
Например, число 0.25 10 в двоичную систему преобразуется точно.
0.125 × 2 = 0.25 | 0 0.25 × 2 = 0.5 | 0 0.5 × 2 = 1 | 1 0.125 10 = 0.001 2
Например, число 0.2 10 можно преобразовать в 2 систему только с определённой точностью:
0.2 × 2 = 0.4 | 0 0.4 × 2 = 0.8 | 0 0.8 × 2 = 1.6 | 1 0.6 × 2 = 1.2 | 1 0.2 × 2 = 0.4 | 0 0.4 × 2 = 0.8 | 0 0.8 × 2 = 1.6 | 1 0.6 × 2 = 1.2 | 1 0.2 × 2 = 0.4 | 0 0.4 × 2 = 0.8 | 0 0.8 × 2 = 1.6 | 1 0.6 × 2 = 1.2 | 1 ... 0.2 10 = 0.001100110011... 2
В результате эти погрешности скажутся при вычисления суммы двух чисел и результатах сравнения. Т.е. получится что на самом деле JavaScript будет видет эту запись следующим образом:
0.6000000000000001==0.6
При вычислениях или отображении чисел с дробной частью необходимо всегда указывать точность, с которой это необходимо делать.
Например, сравнить числа до 2 знаков после запятой используя методы toFixed() и toPrecision() :
//метод toFixed() console.log((0.2+0.4).toFixed(2)==(0.6).toFixed(2)); //true //метод toPrecision() console.log((0.2+0.4).toPrecision(2)==(0.6).toPrecision(2)); //true
Основные математические операцииВ JavaScript существуют следующие математические операторы: + (сложение), - (вычитание), * (умножение), / (деление), % (остаток от деления), ++ (увелить значение на 1), -- (уменьшить значение на 1).
6+3 //9 6-3 //3 6*3 //18 6/3 //2 6%3 //0, т.е. 6:3=2 => 6-3*2 => ост(0) 5%2 //1, т.е. 5:2=2(.5) => 5-2*2 => ост(1) 7.3%2 //1.3, т.е. 7.3:2=3(.65) => 7.3-2*3 => ост(1.3) //знак результата операции % равен знаку первого значения -9%2.5 //-1.5, т.е. 9:2.5=3(.6) => 9-2.5*3 => ост(1.5) -9%-2.5 //-1.5, т.е. 9:2.5=3(.6) => 9-2.5*3 => ост(1.5) -2%5 //-2, т.е. 2:5=0(.4) => 2-5*0 => ост(2) x = 3; console.log(x++); //выводит 3, у уже потом устанавливает 4 console.log(x); //4 x = 3; console.log(++x); //устанавливает 4 и выводит x = 5; console.log(x--); //выводит 5, у уже потом устанавливает 4 console.log(x); //4 x = 5; console.log(--x); //устанавливает 4 и выводит Кроме этого в JavaScript есть комбинированные операторы: x+=y (x=x+y), x-=y (x=x-y), x*=y (x=x*y), x/=y (x=x/y), x%=y (x=x%y). x = 3; y = 6; x+=y; console.log(x); //9 x = 3; y = 6; x-=y; console.log(x); //-3 x = 3; y = 6; x*=y; console.log(x); //18 x = 3; y = 6; x/=y; console.log(x); //0.5 x = 3; y = 6; x%=y; console.log(x); //3
Часто вычисления дают результаты, которые не соответствуют пределам нужных диапазонов. В результате нужно осуществлять JavaScript округление до определенного значения.
Для чего округлять числа?JavaScript не хранит целые числа, поскольку их значения представлены в виде цифр с плавающей точкой. Многие дроби не могут быть представлены числом с определенным конечным количеством знаков после запятой, поэтому JavaScript может генерировать результаты, наподобие приведенного ниже:
0.1 * 0.2; > 0.020000000000000004
На практике это не будет иметь никакого значения, поскольку речь идет о погрешности в 2 квинтилионные. Но это может отразиться на результате при работе с числами, которые представляют значения валют, процентов или размер файла. Поэтому нужно сделать или до определенного знака после запятой.
Округление десятичных чиселЧтобы «обрезать » десятичное число, используются методы toFixed() или toPrecision() . Они оба принимают один аргумент, который определяет количество значимых и знаков после запятой, которые должны быть включены в результат:
- если для toFixed() аргумент не определен, значение по умолчанию равно 0 , то есть без знаков после запятой; максимальное значение аргумента равно 20 ;
- если для toPrecision() аргумент не задан, число не изменяется.
var randNum = 6.25; randNum.toFixed(); > "6" Math.PI.toPrecision(1); > "3" var randNum = 87.335; randNum.toFixed(2); > "87.33" var randNum = 87.337; randNum.toPrecision(3); > "87.3"
Примечание
И toFixed() , и toPrecision возвращают округленное строчное представление результата, а не число. Это означает, что прибавление rounded к randNum в результате даст конкатенацию строк, а не одно число:
console.log(randNum + rounded); > "6.256"
Если нужно получить в результате JavaScript округления до сотых число, используйте parseFloat() :
var randNum = 6.25; var rounded = parseFloat(randNum.toFixed(1)); console.log(rounded); > 6.3
toFixed() и toPrecision() также являются полезными методами для усечения большого количества знаков после запятой. Это удобно при работе с числами, представляющими денежные единицы:
var wholeNum = 1 var dollarsCents = wholeNum.toFixed(2); console.log(dollarsCents); > "1.00"
Обратите внимание, что если в числе больше знаков, чем задано параметром точности, toPrecision будет выдавать результат в научном формате:
var num = 123.435 num.toPrecision(2); > "1.2e+2"
Как избежать ошибок при округлении десятичных дробейВ некоторых случаях toFixed и toPrecision осуществляют JavaScript округление 5 в меньшую сторону , а не до большего:
var numTest = 1.005; numTest.toFixed(2); > 1;
Результатом приведенного выше примера должно быть 1.01, а не 1. Если нужно избежать этой ошибки, я рекомендую использовать экспоненциальные числа:
function round(value, decimals) { return Number(Math.round(value+"e"+decimals)+"e-"+decimals); }
Применение:
round(1.005,2); > 1.01
Если нужно еще более надежное решение, чем округление, оно доступно на MDN .
Округление с помощью эпсилонаАльтернативный метод JavaScript округления до десятых был введен в ES6 (также известном, как JavaScript 2015 ). «Машинный эпсилон » обеспечивает разумный предел погрешности при сравнении двух чисел с плавающей запятой. Без округления, сравнения могут дать результаты, подобные следующим:
0.1 + 0.2 === 0.3 > false
Math.EPSILON может быть использован в функции для получения корректного сравнения:
function epsEqu(x, y) { return Math.abs(x - y) < Number.EPSILON * Math.max(Math.abs(x), Math.abs(y)); }
Функция принимает два аргумента : один содержит вычисления, второй ожидаемый (округленный ) результат. Она возвращает сравнение этих двух параметров:
epsEqu(0.1 + 0.2, 0.3) > true
Все современные браузеры поддерживают математические функции ES6 . Но если необходимо обеспечить поддержку в старых браузерах, то нужно использовать полифиллы .
Усечение десятичных чиселВсе методы, представленные ранее, выполняют JavaScript округление до десятых . Чтобы усечь положительное число до двух знаков после запятой, умножить его на 100 , усечь снова, а затем полученный результат разделить на 100 , нужно:
function truncated(num) { return Math.trunc(num * 100) / 100; } truncated(3.1416) > 3.14
Если требуется что-то более гибкое, можно воспользоваться побитовым оператором:
function truncated(num, decimalPlaces) { var numPowerConverter = Math.pow(10, decimalPlaces); return ~~(num * numPowerConverter)/numPowerConverter; }
Использование:
var randInt = 35.874993; truncated(randInt,3); > 35.874
Округление до ближайшего числаЧтобы осуществить JavaScript округление до целого , используется Math.round() :
Math.round(4.3) > 4 Math.round(4.5) > 5
Обратите внимание, что «половинные значения «, такие как .5 , округляются вверх.
Округление вниз до ближайшего целого числаЕсли вы хотите округлять в меньшую сторону, используйте метод Math.floor() :
Math.floor(42.23); > 42 Math.floor(36.93); > 36
Округление «вниз » имеет одно направление для всех чисел, в том числе и для отрицательных. Это можно представить, как небоскреб с бесконечным количеством этажей, в том числе и ниже уровня фундамента (представляющих отрицательные числа ). Если вы находитесь в лифте между подвальными этажами 2 и 3 (что соответствует значению -2.5 ), Math.floor доставит вас на этаж -3 :
Math.floor(-2.5); > -3
Если нужно избежать этого, используйте JavaScript Math округление с помощью Math.trunc() , поддерживаемый во всех современных браузерах (кроме IE / Edge ):
Math.trunc(-41.43); > -41
MDN также предоставляет полифилл из трех строк для обеспечения поддержки Math.trunc в старых браузерах и IE / Edge .
Округление вверх до ближайшего целого числаЕсли вы хотите округлить десятичные числа вверх, используйте Math.ceil . Действие этого метода также можно представить, как бесконечный лифт: Math.ceil всегда везет вас «вверх «, независимо от того, является ли число отрицательным или положительным:
Math.ceil(42.23); > 43 Math.ceil(36.93); > 37 Math.ceil(-36.93); -36
Округление до ближайшего кратного числаЕсли нужно округлить значение до ближайшего числа, кратного 5 , создайте функцию, которая делит число на 5 , округляет его, а затем умножает результат на то же значение:
function roundTo5(num) { return Math.round(num/5)*5; }
Использование:
roundTo5(11); > 10
Если нужно выполнить JavaScript округление до двух знаков, можно передавать функции, как начальное число, так и кратность:
function roundToMultiple(num, multiple) { return Math.round(num/multiple)*multiple; }
Чтобы использовать функцию, включите в ее вызов округляемое число и кратность:
var initialNumber = 11; var multiple = 10; roundToMultiple(initialNumber, multiple); > 10;
Чтобы округлять значения только в большую или меньшую сторону замените в функции round на ceil или floor .
Привязка к диапазонуИногда нужно получить значение х , которое должно находиться в пределах определенного диапазона. Например, нужно значение от 1 до 100 , но мы получаем значение 123 . Чтобы исправить это, можно использовать min() (возвращает наименьшее из чисел ) и max (возвращает максимально допустимое число ).
Использование:
var lowBound = 1; var highBound = 100; var numInput = 123; var clamped = Math.max(lowBound, Math.min(numInput, highBound)); console.log(clamped); > 100;
Можно создать функцию или расширение класса Number .
Теперь рассмотрим метод floor (в переводе - пол) , который работает противоположно методу ceil , т.е. он округляет дробное число в МЕНЬШУЮ сторону .
var age = 35.97 ;
age = Math .floor (age) ; /* Округляем значение переменной age в меньшую сторону */
document.write (age );
Как видите, метод floor округлил число 35.97 до 35 , то есть в меньшую сторону. Несмотря на то, что 0.97 больше 0.5 (см. ) .
В этом уроке были рассмотрены методы объекта Math , позволяющими округлять дробные десятичные числа .
Теперь нужно выполнить домашнее задание.
Ваша задача написать функцию, которая принимает два параметра.
1. Массив, состоящий из чисел с дробями.
2. Метод округления "round"
, "ceil"
или "floor"
.
На выходе функция должна выводить этот же массив, но при этом все элементы массива, должны быть округлены с помощью указанного во втором параметре метода объекта Math .
Исходный массив:
var numberArray = ;
Сначала решение этого задания может казаться практически идентичным с решениями домашних задач из первых трёх уроков этой темы . Но не все так просто...
Решение №1 - Внимание
По условию задачи функция должна принимать два параметра - исходный массив и один из методов: "round" , "ceil" или "floor" . Исходя из этого, я пробовал сделать так ...
function
decimal
(anyArray
,method
) /* Создаем функцию с двумя параметрами */
{
for (i = 0 ; i < anyArray .length ; i ++ )
{
document.write
(anyArray
"
)
anyArray = Math .method (anyArray ); /* При помощи одного из методов объекта Math округляем текущий элемент массива */
document.write (anyArray + "
"
)
}
decimal (numberArray, round ) /* Вызываем функцию и указываем для нее два параметра. Но НЕЛЬЗЯ указывать ИМЯ метода в качестве параметра функции */
В этом решении создаем функцию с двумя параметрами, а когда ее вызываем, то в качестве параметров
функции пробуем указать исходный массив и ИМЯ одного методов:
decimal
(numberArray,
round
) - в данном случае round
.
Но результата мы не получим, так как НЕЛЬЗЯ указывать ИМЯ метода в качестве параметра функции .
Обратите внимание: ведь не случайно в условии задачи имена методов "round" , "ceil" и "floor" заключены в кавычки .
decimal (numberArray, "round" ) - но такая запись тоже не будет верной!!!
Решение №2 - Корректируем предыдущее решение
Можно решить задачу, указав для функции один параметр.
var numberArray = ;
function
decimal
(anyArray
) /* Создаем функцию с одним параметром */
{
for (i = 0 ; i < anyArray .length ; i ++ ) /* Перебираем элементы массива */
{
document.write
(anyArray
+ " - исходный элемент массива
"
) /* Выводим текущий элемент массива */
/* При помощи метода round объекта Math округляем текущий элемент массива */
document.write (anyArray + " - Округленный элемент
"
) /* Выводим ОКРУГЛЕННЫЙ элемент массива */
}
decimal (numberArray ) /* Вызываем функцию и указываем один параметр - исходный массив */
35 - Округленный элемент
13 - Округленный элемент
17 - Округленный элемент
79 - Округленный элемент
Здесь удалось достичь нужного результата: метод round округлил все числа по . Но не выполнено условие , так как функция принимает лишь один параметр.
Решение №3 - Функция с двумя параметрами
Здесь задача решена правильно. Для этого нужно было вспомнить тему условий в javascript и применить несколько условий одновременно.
var numberArray = ;
function
decimal
(anyArray
,method
)
{
for (i
=
0
; i
<
anyArray
.length
; i
++
)
{
document.write
(anyArray
+ " - исходный элемент массива
"
);
if (method
{
anyArray
= Math
.round
(anyArray
);
document.write
(anyArray
+ " - стандартное округление
"
)
}
Else if(method
{
document.write
(anyArray
+ " - округляем в БОЛЬШУЮ сторону
"
)
}
else if(method
{
document.write
(anyArray
+ " - округляем в МЕНЬШУЮ сторону
"
)
}
}
}
decimal
(numberArray,
"ceil"
)/* Вторым параметром функции - в кавычках указываем имя одного из методов */
34.82 - исходный элемент массива
35 - округляем в БОЛЬШУЮ сторону
12.9 - исходный элемент массива
13 - округляем в БОЛЬШУЮ сторону
17.01 - исходный элемент массива
18 - округляем в БОЛЬШУЮ сторону
78.51 - исходный элемент массива
79 - округляем в БОЛЬШУЮ сторону
Это правильное решение Домашнего задания. Здесь для функции указаны два параметра согласно условию.
Попробуйте в последней строке этого решения:
decimal
(numberArray,
"ceil"
) в качестве второго параметра функции указать имена других методов "round"
и "floor"
объекта Math
.
Решение №4 - Функция с двумя параметрами + метод prompt
Я решил немного оптимизировать предыдущее решение и добавил метод prompt , который вызывает модальное окно, содержащее поле для ввода информации.
Теперь благодаря этому можно будет ввести название одного из методов round , floor или ceil в поле для ввода и получить соответствующий результат.
var numberArray = ;
function
decimal
(anyArray
,method
)
{
for (i
=
0
; i
<
anyArray
.length
; i
++
)
{
document.write
(anyArray
+ " - исходный элемент массива
"
);
if (method
== "round"
) /* 1-е условие */
{
anyArray
= Math
.round
(anyArray
);
document.write
(anyArray
+ "
"
)
}
Else if(method
== "ceil"
) /* 2-е условие */
{
anyArray
= Math
.ceil
(anyArray
);
document.write
(anyArray
+ "
"
)
}
else if(method
== "floor"
) /* 3-е условие */
{
anyArray
= Math
.floor
(anyArray
);
document.write
(anyArray
+ "
"
)
}
/* Добавляем метод prompt */
var method = prompt ("Введите один из методов: round, ceil или floor" );
if (method
== "floor"
) /* 1-е условие */
{
document.write
("Вы ввели метод " +
method
+ " , который округляет числа в МЕНЬШУЮ сторону
"
)
}
else if (method
== "round"
) /* 2-е условие */
{
document.write
("Вы ввели метод " +
method
+ " , который округляет числа по стандартным правилам
"
)
}
else if (method
== "ceil"
) /* 3-е условие */
{
document.write
("Вы ввели метод " +
method
+ " , который округляет числа в БОЛЬШУЮ сторону
"
)
}
else /* Иначе... */
{
document.write
("Вы не ввели или ошибочно ввели метод
"
)
}
decimal (numberArray, method ) /* Вызываем функцию */
Вот так работают методы round , floor или ceil объекта Math , которые округляют дробные числа.