Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Работа с числами в js

Лекция



Привет, сегодня поговорим про числа в js, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое числа в js, работа с числами в js , настоятельно рекомендую прочитать все из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend).


  1. Способы записи
  2. Деление на ноль, Infinity
  3. NaN
  4. isFinite(n)
  5. Преобразование к числу
    1. isNaN — проверка на число для строк
  6. Мягкое преобразование: parseInt и parseFloat
  7. Проверка на число для всех типов
  8. toString(система счисления)
  9. Округление
    1. Округление до заданной точности
    2. num.toFixed(precision)
  10. Неточные вычисления
  11. Другие математические методы
    1. Тригонометрия
    2. Функции общего назначения
  12. Итого

Все числа в JavaScript, как целые так и дробные, имеют тип Number и хранятся в 64-битном форматеIEEE-754, также известном как «double precision».

Здесь мы рассмотрим различные тонкости, связанные с работой с числами в JavaScript.

Способы записи

В JavaScript можно записывать числа не только в десятичной, но и в шестнадцатеричной (начинается с0x), а также восьмеричной (начинается с 0) системах счисления:

 

   
1 alert( 0xFF ); // 255 в шестнадцатиричной системе
2 alert( 010 ); // 8 в восьмеричной системе

 

Также доступна запись в «научном формате» (еще говорят «запись с плавающей точкой»), который выглядит как <число>e<кол-во нулей>.

Например, 1e3 — это 1 с 3 нулями, то есть 1000.

 

   
1 // еще пример научной формы: 3 с 5 нулями
2 alert( 3e5 );  // 300000

 

Если количество нулей отрицательно, то число сдвигается вправо за десятичную точку, так что получается десятичная дробь:

 

   
1 // здесь 3 сдвинуто 5 раз вправо, за десятичную точку.
2 alert( 3e-5 ); // 0.00003  <-- 5 нулей, включая начальный ноль

 

Деление на ноль, Infinity

Представьте, что вы собираетесь создать новый язык… Люди будут называть его «JavaScript» (или LiveScript… неважно).

Что должно происходить при попытке деления на ноль?

Как правило, ошибка в программе… Во всяком случае, в большинстве языков программирования это именно так.

Но создатель JavaScript решил более «математическим» путем. Ведь чем меньше делитель, тем больше результат. При делении на очень-очень маленькое число должно получиться очень большое. В математическом анализе это описывается через пределы, но если упрощенно, то в качестве результата деления на 0 мы получаем «бесконечность», которая обозначается символом  или, в JavaScript: "Infinity".

 

   
1 alert(1/0);  // Infinity
2 alert(12345/0); // Infinity

 

Infinity — особенное численное значение, которое ведет себя в точности как математическая бесконечность .

  • Infinity больше любого числа.
  • Добавление к бесконечности не меняет ее.

 

   
1 alert(Infinity > 1234567890); // true
2 alert(Infinity + 5 == Infinity);  // true

 

Бесконечность можно присвоить и в явном виде: var x = Infinity.

Бывает и минус бесконечность -Infinity:

 

   
1 alert( -1 / 0 ); // -Infinity

 

Бесконечность можно получить также, если сделать ну очень большое число, для которого количество разрядов в двоичном представлении не помещается в соответствующую часть стандартного 64-битного формата, например:

 

   
1 alert( 1e500 ); // Infinity

 

NaN

Если математическая операция не может быть совершена, то возвращается специальное значение NaN (Not-A-Number).

Например, деление 0/0 в математическом смысле неопределено, поэтому возвращает NaN:

 

   
1 alert( 0 / 0 );  // NaN

 

Значение NaN используется для обозначения математической ошибки и обладает следующими свойствами:

  • Значение NaN — единственное, в своем роде, которое не равно ничему, включая себя.

    Следующий код ничего не выведет:

       
    1 if (NaN == NaN) alert("=="); // Ни один вызов
    2 if (NaN === NaN) alert("==="); // не сработает

     

  • Значение NaN можно проверить специальной функцией isNaN(n), которая возвращает true если аргумент — NaN и false для любого другого значения.
       
    1 var n = 0/0;
    2  
    3 alert( isNaN(n) ); // true

     

    Еще один забавный способ проверки значения на NaN — это проверить его на равенство самому себе, вот так:

       
    1 var n = 0/0;
    2  
    3 if (n !== n) alert('n = NaN!');
    Это работает, но для наглядности лучше использовать isNaN.

     

     

  • Значение NaN «прилипчиво». Любая операция с NaN возвращает NaN.
       
    1 alert( NaN + 1 ); // NaN

Если аргумент isNaN — не число, то он автоматически преобразуется к числу.

 

Никакие математические операции в JavaScript не могут привести к ошибке или «обрушить» программу.

В худшем случае, результат будет NaN.

 

isFinite(n)

Итак, в JavaScript есть обычные числа и три специальных числовых значения: NaNInfinity и-Infinity.

Функция isFinite(n) возвращает true только тогда, когда n — обычное число, а не одно из этих значений:

 

   
1 alert( isFinite(1) ); // true
2 alert( isFinite(Infinity) ); // false
3 alert( isFinite(NaN) ); // false

 

Если аргумент isFinite — не число, то он автоматически преобразуется к числу.

Преобразование к числу

Строгое преобразование можно осуществить унарным плюсом '+'

   
1 var s = "12.34";
2 alert( +s );  // 12.34

 

Строгое — означает, что если строка не является в точности числом, то результат будет NaN:

   
1 alert( +"12test" );  // NaN

 

Единственное исключение — пробельные символы в начале и в конце строки, которые игнорируются:

   
1 alert( +"  -12");  // -12
2 alert( +" \n34  \n"); // 34, перевод строки \n является пробельным символом
3 alert( +"" ); // 0, пустая строка становится нулем
4 alert( +"1 2" ); // NaN, пробел посередине числа - ошибка

 

Аналогичным образом происходит преобразование и в других математических операторах и функциях:

 

   
1 alert( '12.34' "-2" );  // -6.17

 

 

Важность: 5

Создайте страницу, которая предлагает ввести два числа и выводит их сумму.

Работать должно так: tutorial/intro/sum.html.

P.S. Есть «подводный камень» при работе с типами.

Решение

tutorial/intro/sum.html

[Открыть задачу в новом окне]

 

isNaN — проверка на число для строк

Функция isNaN является математической, она преобразует аргумент в число, а затем проверяет, NaNэто или нет.

Поэтому можно использовать ее для проверки:

 

   
1 var x = "-11.5";
2 if (isNaN(x)) {
3   alert("Строка преобразовалась в NaN. Не число"); 
4 else {
5   alert("Число");
6 }

 

Единственный тонкий момент — в том, что пустая строка и строка из пробельных символов преобразуются к 0:

 

   
1 alert(isNaN(" \n\n  ")) // false, т.к. строка из пробелов преобразуется к 0

 

И, конечно же, проверка isNaN посчитает числами значения false, true, null, т.к. они хотя и не числа, но преобразуются к ним:

 

1 +false = 0
2 +true = 1
3 +null = 0        
4 +undefined = NaN;

 

Мягкое преобразование: parseInt и parseFloat

В мире HTML/CSS многие значения не являются в точности числами. Например, метрики CSS: 10ptили -12px.

Оператор '+' для таких значений возвратит NaN:

   
1 alert( +"12px" // NaN

 

Для удобного чтения таких значений существует функция parseInt:

   
1 alert( parseInt('12px') ); // 12

 

parseInt и ее аналог parseFloat преобразуют строку символ за символом, пока это возможно.

При возникновении ошибки возвращается число, которое получилось. parseInt читает из строки целое число, а parseFloat — дробное.

 

   
1 alert( parseInt('12px') ) // 12, ошибка на символе 'p'
2 alert( parseFloat('12.3.4') ) // 12.3, ошибка на второй точке

 

Конечно, существуют ситуации, когда parseInt/parseFloat возвращают NaN. Об этом говорит сайт https://intellect.icu . Это происходит при ошибке на первом же символе:

 

   
1 alert( parseInt('a123') ); // NaN

 

 

Ошибка parseInt('0..')

parseInt (но не parseFloat) понимает 16-ричную систему счисления:

   
1 alert( parseInt('0xFF') ) // 255

 

В старом стандарте JavaScript он умел понимать и восьмеричную:

   
1 alert( parseInt('010') )  // в некоторых браузерах 8

 

Если вы хотите быть уверенным, что число, начинающееся с нуля, будет интерпретировано верно — используйте второй необязательный аргумент parseInt— основание системы счисления:

 

   
1 alert( parseInt('010', 10) ); // во всех браузерах 10

 

 

Проверка на число для всех типов

Если вам нужна действительно точная проверка на число, которая не считает числом строку из пробелов, логические и специальные значения — используйте следующую функцию isNumeric:

function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

 

Разберемся, как она работает. Начнем справа.

  • Функция isFinite(n) преобразует аргумент к числу и возвращает true, если это неInfinity/-Infinity/NaN.

    Таким образом, правая часть отсеет заведомо не-числа, но оставит такие значения какtrue/false/null и пустую строку '', т.к. они корректно преобразуются в числа.

  • Для их проверки нужна левая часть. Вызов parseFloat(true/false/null/'') вернет NaN для этих значений.

    Так устроена функция parseFloat: она преобразует аргумент к строке, т.е. true/false/nullстановятся "true"/"false"/"null", а затем считывает из нее число, при этом пустая строка дает NaN.

В результате отсеивается все, кроме строк-чисел и обычных чисел.

toString(система счисления)

Как показано выше, числа можно записывать не только в 10-чной, но и в 16-ричной системе. Но бывает и противоположная задача: получить 16-ричное представление числа. Для этого используется методtoString(основание системы), например:

 

   
1 var n = 255;
2  
3 alert( n.toString(16) ); // ff

 

Основание может быть любым от 2 до 36.

  • Основание 2 бывает полезно для отладки битовых операций, которые мы пройдем чуть позже:
       
    1 var n = 4;
    2 alert( n.toString(2) ); // 100
  • Основание 36 (по количеству букв в английском алфавите — 26, вместе с цифрами, которых 10) используется для того, чтобы «кодировать» число в виде буквенно-цифровой строки. В этой системе счисления сначала используются цифры, а затем буквы от a до z:
       
    1 var n = 1234567890;
    2 alert( n.toString(36) ); // kf12oi

    При помощи такого кодирования можно сделать длинный цифровой идентификатор короче, чтобы затем использовать его в URL.

Округление

Одна из самых частых операций с числом — округление. В JavaScript существуют целых 3 функции для этого.

Math.floor
Округляет вниз
Math.ceil
Округляет вверх
Math.round
Округляет до ближайшего целого

 

   
1 alert( Math.floor(3.1) );  // 3
2 alert( Math.ceil(3.1) );   // 4
3 alert( Math.round(3.1) );  // 3

 

 

Округление битовыми операторами

Битовые операторы делают любое число 32-битным целым, обрезая десятичную часть.

В результате побитовая операция, которая не изменяет число, например, двойное битовое НЕ — округляет его:

 

   
1 alert( ~~12.3 );  // 12

 

Любая побитовая операция такого рода подойдет, например XOR (исключающее ИЛИ,"^") с нулем:

 

   
1 alert( 12.3 ^ 0 );  // 12
2 alert( 1.2 + 1.3 ^ 0); // 2, приоритет ^ меньше, чем +

 

Это удобно в первую очередь тем, что легко читается и не заставляет ставить дополнительные скобки как Math.floor(...):

var x = a * b / c ^ 0; // читается так: "a*b/c и округлить"

 

 

Округление до заданной точности

Обычный трюк — это умножить и поделить на 10 с нужным количеством нулей. Например, округлим3.456 до 2го знака после запятой:

 

   
1 var n = 3.456;
2 alert( Math.round( n * 100 ) / 100 );  // 3.456 -> 345.6 -> 346 -> 3.46

 

Таким образом можно округлять число и вверх и вниз.

num.toFixed(precision)

Существует специальный метод num.toFixed(precision), который округляет число num до точностиprecision и возвращает результат в виде строки:

 

   
1 var n = 12.34;
2 alert( n.toFixed(1) ); // "12.3"

 

Округление идет до ближайшего значения, аналогично Math.round:

 

   
1 var n = 12.36;
2 alert( n.toFixed(1) ); // "12.4"

 

Итоговая строка, при необходимости, дополняется нулями до нужной точности:

 

   
1 var n = 12.34;
2 alert( n.toFixed(5) ); // "12.34000", добавлены нули до 5 знаков после запятой

 

Если нам нужно именно число, то мы можем получить его, применив '+' к результату n.toFixed(..):

 

   
1 var n = 12.34;
2 alert( +n.toFixed(5) ); // 12.34

 

 

Метод toFixed не эквивалентен Math.round!

Например, произведем округление до одного знака после запятой с использованием двух способов:

   
1 var price = 6.35;
2  
3 alert( price.toFixed(1) ); // 6.3
4 alert( Math.round(price*10)/10 ); // 6.4
Как видно, результат разный! Вариант округления через Math.round получился более корректным, так как по общепринятым правилам 5 округляется вверх. А toFixedможет округлить его как вверх, так и вниз. Почему? Скоро узнаем!

 

 

Неточные вычисления

Запустите этот пример:

   
1 alert(0.1 + 0.2 == 0.3);

 

Запустили? Если нет — все же сделайте это.

Ок, вы запустили его. Результат несколько странный, не так ли? Возможно, ошибка в браузере? Поменяйте браузер, запустите еще раз.

Хорошо, теперь мы можем быть уверены: 0.1 + 0.2 это не 0.3. Но тогда что же это?

 

   
1 alert(0.1 + 0.2); // 0.30000000000000004

 

Как видите, произошла небольшая вычислительная ошибка.

Дело в том, что в стандарте IEEE 754 на число выделяется ровно 8 байт(=64 бита), не больше и не меньше.

Число 0.1 (=1/10) короткое в десятичном формате, а в двоичной системе счисления это бесконечная дробь (перевод десятичной дроби в двоичную систему). Также бесконечной дробью является0.2 (=2/10).

Двоичное значение бесконечных дробей хранится только до определенного знака, поэтому возникает неточность. Это даже можно увидеть:

 

   
1 alert( 0.1.toFixed(20) );  // 0.10000000000000000555

 

Когда мы складываем 0.1 и 0.2, то две неточности складываются, получаем третью.

Конечно, это не означает, что точные вычисления для таких чисел невозможны. Они возможны. И даже необходимы.

Например, есть два способа сложить 0.1 и 0.2:

  1. Сделать их целыми, сложить, а потом поделить:
       
    1 alert( (0.1*10 + 0.2*10) / 10 ); // 0.3

    Это работает, т.к. числа 0.1*10 = 1 и 0.2*10 = 2 могут быть точно представлены в двоичной системе.

  2. Сложить, а затем округлить до разумного знака после запятой. Округления до 10-го знака обычно бывает достаточно, чтобы отсечь ошибку вычислений:
       
    1 var result = 0.1 + 0.2;
    2 alert( +result.toFixed(10) ); // 0.3

 

Важность: 4

В математике принято, что 5 округляется вверх, например:

   
1 alert( 1.5.toFixed(0) ); // 2
2 alert( 1.35.toFixed(1) ); // 1.4

 

Но почему в примере ниже 6.35 округляется до 6.3?

   
1 alert( 6.35.toFixed(1) ); // 6.3

 

Решение

Во внутреннем двоичном представлении 6.35 является бесконечной двоичной дробью. Хранится она с потерей точности.. А впрочем, посмотрим сами:

 

   
1 alert( 6.35.toFixed(20) ); // 6.34999999999999964473

 

Интерпретатор видит число как 6.34..., поэтому и округляет вниз.

[Открыть задачу в новом окне]

 

 

Важность: 5

Представьте себе электронный магазин. Цены даны с точностью до копейки(цента, евроцента и т.п.).

Вы пишете интерфейс для него. Основная работа происходит на сервере, но и на клиенте все должно быть хорошо. Сложение цен на купленные товары и умножение их на количество является обычной операцией.

Получится глупо, если при заказе двух товаров с ценами 0.10$ и 0.20$ человек получит общую стоимость 0.30000000000000004$:

 

   
1 alert( 0.1 + 0.2 + '$' );

 

Что можно сделать, чтобы избежать проблем с ошибками округления?

Решение

Есть два основных подхода.

  1. Можно хранить сами цены в «копейках» (центах и т.п.). Тогда они всегда будут целые и проблема исчезнет. Но при показе и при обмене данными нужно будет это учитывать и не забывать делить на 100.
  2. При операциях, когда необходимо получить окончательный результат — округлять до 2го знака после запятой. Все, что дальше — ошибка округления:
       
    1 var price1 = 0.1, price2 = 0.2;
    2 alert( +(price1 + price2).toFixed(2) );
[Открыть задачу в новом окне]

 

 

Забавный пример

Привет! Я — число, растущее само по себе!

   
1 alert(9999999999999999);

 

Причина та же — потеря точности.

Из 64 бит, отведенных на число, сами цифры числа занимают до 52 бит, остальные 11бит хранят позицию десятичной точки и один бит — знак. Так что если 52 бит не хватает на цифры, то при записи пропадут младшие разряды.

Интерпретатор не выдаст ошибку, но в результате получится «не совсем то число», что мы и видим в примере выше. Как говорится: «как смог, так записал».

 

Ради справедливости заметим, что в точности то же самое происходит в любом другом языке, где используется формат IEEE 754, включая Java, C, PHP, Ruby, Perl.

Другие математические методы

JavaScript предоставляет базовые тригонометрические и некоторые другие функции для работы с числами.

Тригонометрия

Встроенные функции для тригонометрических вычислений:

Math.acos(x)
Возвращает арккосинус x (в радианах)
Math.asin(x)
Возвращает арксинус x (в радианах)
Math.atan
Возвращает арктангенс x (в радианах)
Math.atan2(y, x)
Возвращает угол до точки (y, x). Описание функции: Atan2.
Math.sin(x)
Вычисляет синус x (в радианах)
Math.cos(x)
Вычисляет косинус x (в радианах)
Math.tan(x)
Возвращает тангенс x (в радианах)

Функции общего назначения

Разные полезные функции:

Math.sqrt(x)
Возвращает квадратный корень из x.
Math.log(x)
Возвращает натуральный (по основанию e) логарифм x.
Math.pow(x, exp)
Возводит число в степень, возвращает xexp, например Math.pow(2,3) = 8. Работает в том числе с дробными и отрицательными степенями, например: Math.pow(4, -1/2) = 0.5.
Math.abs(x)
Возвращает абсолютное значение числа
Math.exp(x)
Возвращает ex, где e — основание натуральных логарифмов.
Math.max(a, b, c...)
Возвращает наибольший из списка аргументов
Math.min(a, b, c...)
Возвращает наименьший из списка аргументов
Math.random()
Возвращает псевдо-случайное число в интервале [0,1) - то есть между 0(включительно) и 1(не включая). Генератор случайных чисел инициализуется текущим временем.

Итого

  • Числа могут быть записаны в шестнадцатиричной, восьмеричной системе, а также «научным» способом.
  • В JavaScript существует числовое значение бесконечность Infinity.
  • Ошибка вычислений дает NaN.
  • Арифметические и математические функции преобразуют строку в точности в число, игнорируя начальные и конечные пробелы.
  • Функции parseInt/parseFloat делают числа из строк, которые начинаются с числа.
  • Есть четыре способа округления: Math.floorMath.roundMath.ceil и битовый оператор. Для округления до нужного знака используйте +n.toFixed(p) или трюк с умножением и делением на10p.
  • Дробные числа дают ошибку вычислений. При необходимости ее можно отсечь округлением до нужного знака.
  • Случайные числа от 0 до 1 генерируются с помощью Math.random(), остальные — преобразованием из них.

Существуют и другие математические функции. Вы можете ознакомиться с ними в справочнике в разделах Number и Math.

 

Важность: 4

Этот цикл - бесконечный. Почему?

1 var i = 0;
2 while(i != 10) {
3   i += 0.2;
4 }

 

Решение

Потому что i никогда не станет равным 10.

Запустите, чтобы увидеть реальные значения i:

   
1 var i = 0;
2 while(i < 11) {
3   i += 0.2;
4   if (i>9.8 && i<10.2) alert(i);
5 }

 

Ни одно из них в точности не равно 10.

[Открыть задачу в новом окне]

 

 

Важность: 3

Напишите функцию getDecimal(num), которая возвращает десятичную часть положительного числа:

alert( getDecimal(12.5) ); // 0.5
alert( getDecimal(6.25) ); // 0.25

 

Пожалуйста, не преобразуйте число к строке в процессе.

Ответьте на два вопроса:

  • Точно ли работает ваша функция для большинства чисел?
  • Если нет, но при этом есть информация, что дробная часть может быть не больше 6 знаков после запятой — можно ли поправить функцию, чтобы работала корректно?
Решение
Функция

Функция может быть такой:

   
1 function getDecimal(num) {
2   return num - Math.floor(num);
3 }
4  
5 alert( getDecimal(12.5) ); // 0.5
6 alert( getDecimal(6.25) ); // 0.25

 

…Или, гораздо проще, такой:

function getDecimal(num) {
  return num % 1;
}

 

Числа

Обычно функция работает неправильно из-за неточных алгоритмов работы с дробями.

Например:

   
1 alert( 1.2 % 1 ); // 0.19999999999999996
2 alert( 1.3 % 1 ); // 0.30000000000000004
3 alert( 1.4 % 1 ); // 0.3999999999999999

 

Исправление

Можно добавить округление toFixed, которое отбросит лишние знаки:

 

   
1 function getDecimal(num) {
2   return +(num % 1).toFixed(6);
3 }
4  
5 alert( getDecimal(1.2) ); // 0.2
6 alert( getDecimal(1.3) ); // 0.3
7 alert( getDecimal(1.4) ); // 0.4

 

[Открыть задачу в новом окне]

 

 

Важность: 4

Последовательность чисел Фибоначчи имеет формулуFn = Fn-1 + Fn-2. То есть, следующее число получается как сумма двух предыдущих.

Первые два числа равны 1, затем 2(1+1), затем 3(1+2)5(2+3) и так далее:1, 1, 2, 3, 5, 8, 13, 21....

Код для их вычисления (из задачи Числа Фибоначчи):

1 function fib(n){
2   var a=1, b=0, x;
3   for(i=0; i<n; i++) {
4     x = a+b;
5     a = b
6     b = x;
7   }
8   return b;
9 }

 

Существует формула Бине, согласно которой Fn равно ближайшему целому дляϕn/√5, где ϕ=(1+√5)/2 — золотое сечение.

Напишите функцию fib(n), которая будет вычислять Fn, используя эту формулу. Проверьте ее для значенияF77 (должно получиться fib(77) = 5527939700884757).

Правилен ли полученный результат? Если нет, то почему?

Решение

Вычисление по следствию из формулы Бине:

 

   
1 function fib(n) {
2   var phi = (1 + Math.sqrt(5)) / 2;
3   return Math.round( Math.pow(phi, n) / Math.sqrt(5) );
4 }
5  
6 alert( fib(2) ); // 1, верно
7 alert( fib(8) ); // 21, верно
8 alert( fib(77)); // 5527939700884755 != 5527939700884757, неверно!

 

Обратите внимание — при вычислении используется округление Math.round, т.к. нужно именно ближайшее целое.

Результат вычисления F77 неправильный!

Он отличается от вычисленного другим способом. Причина — в ошибках округления, ведь √5 — бесконечная дробь.

Ошибки округления при вычислениях множатся и, в итоге, дают расхождение.

[Открыть задачу в новом окне]

 

 

Важность: 2

Напишите код для генерации случайного значения в диапазоне от 0 доmax, не включая max.

Решение

Сгенерируем значение в диапазоне 0..1 и умножим на max:

 

   
1 var max = 10;
2  
3 alert( Math.random()*max );

 

[Открыть задачу в новом окне]

 

 

Важность: 2

Напишите код для генерации случайного числа от min до max, не включая max.

Решение

Сгенерируем значение из интервала 0..max-min, а затем сдвинем на min:

 

   
1 var min=5, max = 10;
2  
3 alert( min + Math.random()*(max-min) );

 

[Открыть задачу в новом окне]

 

 

Важность: 2

Напишите код для генерации случайного целого числа между min и max, включая min,max как возможные значения.

Любое число из интервала min..max должно иметь одинаковую вероятность.

Решение
Очевидное неверное решение (round)

Самый простой, но неверный способ - это сгенерировать значение в интервалеmin..max и округлить его Math.round, вот так:

var rand = min + Math.random()*(max-min)
rand = Math.round(rand);

 

Оно работает. Но при этом вероятность получить крайние значения min и max будет в два раза меньше, чем любые другие.

Например, давайте найдем значения между 1 и 3 этим способом:

 

// случайное число от 1 до 3, не включая 3
var rand = 1 + Math.random()*(3-1)

 

Вызов Math.round() округлит значения следующим образом:

значения из диапазона 1   ... 1.499+  станут 1
значения из диапазона 1.5 ... 2.499+  станут 2
значения из диапазона 2.5 ... 2.999+  станут 3

 

Отсюда уже видно, что в 1 (как и 3) попадает диапазон в два раза меньший, чем в 2. Так что 1 будет выдаваться в два раза реже, чем 2.

Верное решение с round

Правильный способ: Math.round(случайное от min-0.5 до max+0.5)

 

   
1 var min = 1, max = 3;
2  
3 var rand = min - 0.5 + Math.random()*(max-min+1)
4 rand = Math.round(rand);
5  
6 alert(rand);

 

В этом случае диапазон будет тот же (max-min+1), но учтена механика округленияround.

Решение с floor

Альтернативный путь - применить округление Math.floor() к случайному числу отmin до max+1.

Например, для генерации целого числа от 1 до 3, создадим вспомогательное случайное значение от 1 до 4 (не включая 4).

Тогда Math.floor() округлит их так:

1 ... 1.999+ станет 1
2 ... 2.999+ станет 2
3 ... 3.999+ станет 3

 

Все диапазоны одинаковы.
Итак, код:

 

   
1 var min=5, max=10;
2 var rand = min + Math.random()*(max+1-min);
3 rand = rand^0; // округление битовым оператором
4 alert(rand);

 

[Открыть задачу в новом окне]

К сожалению, в одной статье не просто дать все знания про числа в js. Но я - старался. Если ты проявишь интерес к раскрытию подробностей,я обязательно напишу продолжение! Надеюсь, что теперь ты понял что такое числа в js, работа с числами в js и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)

создано: 2014-10-07
обновлено: 2021-03-13
132572



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей



Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)

Термины: Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)