Math.round()

Случайное число

Метод Math.random() генерирует
псевдо-случайное число в диапазоне от 0 до 1. При
этом ровно 1 не бывает, число вегда будет меньше.

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

случайное число = минимум + Math.random() * (максимум — минимум)

Для примера выведем число в диапазоне от -2 до 5:

1617
var rand = -2 + Math.random() * (5 - (-2));
console.log(rand);

Конечно, 5 — (-2) это 5+2.

Не завбывайте, что число 5 Вы в этой формуле не получите. Максимальное будет
4.999999999. Полученные значения можно округлить до нужной точности.

Если нужны только целые числа, то полученные значения можно округлять до целого в меньшую сторону. К
максимуму нужно прибавить единицу, чтобы этот максимум тоже был возможен. Формула получается такая:

целое число = Math.floor (минимум + Math.random() * (максимум+1 — минимум))

Выведем числа от 10 до 15:

1920
rand = Math.floor(10 + Math.random() * (15 + 1 - 10));
console.log(rand);

Math Object Methods

Method Description
abs(x) Returns the absolute value of x
acos(x) Returns the arccosine of x, in radians
acosh(x) Returns the hyperbolic arccosine of x
asin(x) Returns the arcsine of x, in radians
asinh(x) Returns the hyperbolic arcsine of x
atan(x) Returns the arctangent of x as a numeric value between -PI/2 and PI/2 radians
atan2(y, x) Returns the arctangent of the quotient of its arguments
atanh(x) Returns the hyperbolic arctangent of x
cbrt(x) Returns the cubic root of x
ceil(x) Returns x, rounded upwards to the nearest integer
clz32(x) Returns the number of leading zeros in a 32-bit binary representation of x
cos(x) Returns the cosine of x (x is in radians)
cosh(x) Returns the hyperbolic cosine of x
exp(x) Returns the value of Ex
expm1(x) Returns the value of Ex minus 1
floor(x) Returns x, rounded downwards to the nearest integer
fround(x) Returns the nearest (32-bit single precision) float representation of a number
log(x) Returns the natural logarithmof x
log10(x) Returns the base-10 logarithm of x
log1p(x) Returns the natural logarithm of 1 + x
log2(x) Returns the base-2 logarithm of x
max(x, y, z, …, n) Returns the number with the highest value
min(x, y, z, …, n) Returns the number with the lowest value
pow(x, y) Returns the value of x to the power of y
random() Returns a random number between 0 and 1
round(x) Rounds x to the nearest integer
sign(x) Returns the sign of a number (checks whether it is positive, negative or zero)
sin(x) Returns the sine of x (x is in radians)
sinh(x) Returns the hyperbolic sine of x
sqrt(x) Returns the square root of x
tan(x) Returns the tangent of an angle
tanh(x) Returns the hyperbolic tangent of a number
trunc(x) Returns the integer part of a number (x)

❮ Previous
Next ❯

Как явно преобразовать строку в число

Явно привести строку в число можно посредством следующих способов:

1. Использовать унарный оператор +, который необходимо поместить перед значением.

+'7.35';   // 7.35
+'текст';  // NaN

Этот способ пренебрегает пробелами в начале и конце строки, а также (переводом строки).

+' 7.35 ';    //7.35
+'7.35 \n ';  //7.35

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

+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).

Выбор способа округления

Существует несколько способов округления в зависимости от способа применения результата: округление к меньшему/ большему, округление к меньшему/ большему по модулю, округление к ближайшему целому, округление к ближайшему чётному и т. д… Округление к ближайшему целому, в свою очередь, можно делать по-разному в зависимости от того, какой результат должен получиться, если дробная часть равна 0,5. Я буду рассматривать округление к ближайшему целому, причём 0,5 будет округляться в большую (по модулю) сторону.

Требования к корректной реализации Round() заключаются в следующем:

  • правильно округляет до ближайшего целого все конечные числа;
  • поддерживает специальные значения (NaN, Inf, -0), возвращая их без изменений.

Я буду использовать следующие тестовые примеры для проверки корректности, в каждой паре содержатся исходное значение и предполагаемый результат выполнения функции Round():

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

Обратите внимание, что, поскольку мы используем float, мы не можем использовать число 0,49999999999999999 в качестве ближайшего к 0,5, так как из-за ограниченной точности float это число в точности равно 0,5. Вместо этого я использую 0,49999999999999994

Реализации, предложенные в закрытом тикете, явно не были проверены на подобных данных, часто не работали даже те из них, которые были предложены известными людьми. Это лишний раз доказывает, насколько сложно написать Round().

int(f + 0.5)

Первая реализация, предложенная rsc, выглядела следующим образом:

Она некорректно работает с особыми значениями, отрицательными числами, числами больше math.MaxInt64 и числами, близкими к 0,5:

Floor() or Ceil()

Второй предложенный вариант учитывал отрицательные числа:

однако продолжал некорректно работать в некоторых случаях:

Первые два теста не проходят, потому что результат разности n — 0,5 равен в точности -1,0, тогда как мы ожидаем получить что-то точно большее, чем -1,0. Если посмотреть на , можно понять, как решить эту проблему.

Самое интересное, что эта ошибка не является такой уж редкой. До версии 6 точно такая же присутствовала в Java. Хорошо, что с тех пор реализация улучшилась.

int и Copysign

В третьем предложении от minux была предпринята другая попытка решить проблему отрицательных чисел:

И этот вариант всё равно ломает тесты:

Как видно, часть тестов стала проходить, однако другие начали падать. Была предпринята попытка улучшить этот алгоритм:

Однако и она провалилась:

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

Мы рассмотрели уже четыре варианта, и в каждом из них нашлись изъяны. Настало время посмотреть, как Round() реализуют авторы различных пакетов.

Kubernetes

Kubernetes 1.7 содержит реализацию:

Она ломает следующие тесты:

Судя по тому, что функция возвращает int32, она не предназначена для работы с большими числами. Однако она некорректно работает и с числами, которые близки к 0,5.

Усечение десятичных чисел

Все методы, представленные ранее, выполняют 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

Работающие реализации на Go

Round(), используемая в Postgres

Выше я уже упоминал, что в Postgres содержится код функции Round() на C, который работает для всех тестируемых значений. В CockroachDB мы , без комментариев он выглядит следующим образом:

Давайте разберёмся, как он работает. Первые шесть строк обрабатывают особые случаи. Далее мы выбираем roundFn из Ceil и Floor в зависимости от того, положительное число или отрицательное. Далее начинается самое интересное:

Этим кодом мы сдвигаем x ближе к нулю.

Далее мы проверяем, не стал ли x в точности нулём и не поменялся ли у него знак. Это означает что исходное число <= 0,5, в этом случае мы возвращаем ноль с нужным знаком.

Эта проверка нужна для очень больших чисел, для которых x-0,5 == x-1,0, в этих случаях мы можем вернуть число неизменённым.

Далее мы округляем число с помощью Floor() или Ceil() и возвращаем это значение, если оно отличается от x, что может случиться, только если дробная часть входного значения не равна в точности 0,5, так как выше мы вычли 0,5 из него.

Теперь мы знаем, что дробная часть равна 0,5, поэтому нам нужно округлить до ближайшего чётного числа (реализация Round() в Postgres в этом месте отличается от приведённых выше вариантов). Комментарий в коде лучше это описывает:

Чтобы сохранить оригинальное поведение, этот код можно заменить на следующий:

github.com/montanaflynn/stats

Ещё одна работающая реализация содержится в пакете github.com/montanaflynn/stats. Без комментариев она выглядит следующим образом:

Ключевое отличие от предыдущих решений заключается в использовании функции Modf(), которая корректно разделяет целую и дробную части чисел.

Важные заметки о числах

Для начала запомните, что в js все виды чисел (дробные и целые) относятся к типу Number
. К тому же все они 64-битные, так как хранятся в формате «double precision», который также известен под стандартом IEEE-754.

Создаются численные переменные привычным способом:

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

В появилась поддержка очень интересного метода toLocaleString ()
, который форматирует все числовые параметры по спецификациям, прописанным в ECMA 402. Благодаря этому большие числа, телефонные номера, валюты и даже проценты красиво выводятся в диалоговом окне.

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

Помимо этого, существуют и другие методы, которые выполняют округление числовых значений до целых чисел, до десятых, сотых и т.д. Рассмотрим их все подробнее.

Великий и могучий Math

Глобальный объект Math включает в себя огромное количество разнообразных математических и тригонометрических функций. Это очень нужный объект и часто выручает разработчиков при работе с цифровыми данными.

На других платформах существуют аналогии Math. Например, в таких популярных языках, как Java и C#, Math представляет собой класс, который поддерживает все те же стандартные функции. Так что как видите этот инструмент действительно великий и могучий.

Теперь я хочу пройтись по конкретным методам, отвечающим за округление, и подробно о них рассказать.

Math.floor ()

Начну с Math.
floor

Обратите внимание на наименование метода. Логически становится понятно, что раз речь идет об округлении, а дословный перевод слова «floor» означает «пол», то данный инструмент округлит обрабатываемые значения в меньшую строну

Также возможен вариант, когда обработанное число с помощью этой функции осталось прежним. Все потому, что округление осуществляется по нестрогому неравенству (

в ответе будет число 4.

Math.ceil ()

Опять-таки посмотрите на название (в такой способ материал быстрее усваивается). Если кто-то не знает, то «ceil» означает «потолок». Значит округление числовых данных будет осуществляться в большую сторону, используя нестрогое неравенство (>=).

Как вы уже догадались, в ответе будет число 5.

Math.round ()

Данный метод округляет дробное число до ближайшего целого. Так, если дробная часть находится в диапазоне от 0 и до 0.5 не включительно, то округление происходит к меньшему значению. А если дробная часть находится в диапазоне от включительно 0.5 и до следующего целого числа, то она округляется к большему целому.

Надеюсь, все подумали или сказали правильный ответ – 5.

Устройство чисел с плавающей точкой

Тип может хранить значения в диапазоне до . Такой гигантский диапазон значений (по сравнению с типом ) объясняется тем, что тип (как и ) устроен совсем иначе по сравнению с целыми типами. Каждая переменная типа содержит два числа: первое называется мантисса, а второе — степень.

Допустим, у нас есть число , и мы сохранили его в переменную типа . Тогда число будет преобразовано к виду , и внутри типа будут храниться два числа — и . Красным выделена «значащая часть числа» (манти́сса), синим — степень.

Такой подход позволяет хранить как очень большие числа, так и очень маленькие. Но т.к. размер числа ограничен 8 байтами (64 бита) и часть бит используется под хранение
степени (а также знака числа и знака степени), максимальная длина
мантиссы ограничена 15 цифрами.

JavaScript

JS Array
concat()
constructor
copyWithin()
entries()
every()
fill()
filter()
find()
findIndex()
forEach()
from()
includes()
indexOf()
isArray()
join()
keys()
length
lastIndexOf()
map()
pop()
prototype
push()
reduce()
reduceRight()
reverse()
shift()
slice()
some()
sort()
splice()
toString()
unshift()
valueOf()

JS Boolean
constructor
prototype
toString()
valueOf()

JS Classes
constructor()
extends
static
super

JS Date
constructor
getDate()
getDay()
getFullYear()
getHours()
getMilliseconds()
getMinutes()
getMonth()
getSeconds()
getTime()
getTimezoneOffset()
getUTCDate()
getUTCDay()
getUTCFullYear()
getUTCHours()
getUTCMilliseconds()
getUTCMinutes()
getUTCMonth()
getUTCSeconds()
now()
parse()
prototype
setDate()
setFullYear()
setHours()
setMilliseconds()
setMinutes()
setMonth()
setSeconds()
setTime()
setUTCDate()
setUTCFullYear()
setUTCHours()
setUTCMilliseconds()
setUTCMinutes()
setUTCMonth()
setUTCSeconds()
toDateString()
toISOString()
toJSON()
toLocaleDateString()
toLocaleTimeString()
toLocaleString()
toString()
toTimeString()
toUTCString()
UTC()
valueOf()

JS Error
name
message

JS Global
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
escape()
eval()
Infinity
isFinite()
isNaN()
NaN
Number()
parseFloat()
parseInt()
String()
undefined
unescape()

JS JSON
parse()
stringify()

JS Math
abs()
acos()
acosh()
asin()
asinh()
atan()
atan2()
atanh()
cbrt()
ceil()
clz32()
cos()
cosh()
E
exp()
expm1()
floor()
fround()
LN2
LN10
log()
log10()
log1p()
log2()
LOG2E
LOG10E
max()
min()
PI
pow()
random()
round()
sign()
sin()
sqrt()
SQRT1_2
SQRT2
tan()
tanh()
trunc()

JS Number
constructor
isFinite()
isInteger()
isNaN()
isSafeInteger()
MAX_VALUE
MIN_VALUE
NEGATIVE_INFINITY
NaN
POSITIVE_INFINITY
prototype
toExponential()
toFixed()
toLocaleString()
toPrecision()
toString()
valueOf()

JS OperatorsJS RegExp
constructor
compile()
exec()
g
global
i
ignoreCase
lastIndex
m
multiline
n+
n*
n?
n{X}
n{X,Y}
n{X,}
n$
^n
?=n
?!n
source
test()
toString()

(x|y)
.
\w
\W
\d
\D
\s
\S
\b
\B
\0
\n
\f
\r
\t
\v
\xxx
\xdd
\uxxxx

JS Statements
break
class
continue
debugger
do…while
for
for…in
for…of
function
if…else
return
switch
throw
try…catch
var
while

JS String
charAt()
charCodeAt()
concat()
constructor
endsWith()
fromCharCode()
includes()
indexOf()
lastIndexOf()
length
localeCompare()
match()
prototype
repeat()
replace()
search()
slice()
split()
startsWith()
substr()
substring()
toLocaleLowerCase()
toLocaleUpperCase()
toLowerCase()
toString()
toUpperCase()
trim()
valueOf()

Форматирование чисел

В JavaScript отформатировать вывод числа в соответствии с региональными стандартами (языковыми настройками операционной системы) позволяет метод toLocaleString() .

Например, выполним форматирование числа в соответствии с региональными стандартами, которые установлены в системе по умолчанию:

Var number = 345.46;
console.log(number.toLocaleString()); //»345,46″

Например, выполним форматирование числа в соответствии с региональными стандартами России (ru):

Console.log((108.1).toLocaleString(«ru-RU»)); //»108,1″

Данный метод можно также использовать для форматирования числа в виде валюты:

Console.log((2540.125).toLocaleString(«ru-RU»,{style:»currency», currency:»RUB»})); //»2 540,13 ₽»
console.log((89.3).toLocaleString(«ru-RU»,{style:»currency», currency:»USD»})); //»89,30 $»
console.log((2301.99).toLocaleString(«ru-RU»,{style:»currency», currency:»EUR»})); //»2 301,99 €»

Представление числа в виде процентов:

Console.log((0.45).toLocaleString(«ru-RU»,{style:»percent»})); //»45 %»

Разбить число на разряды (свойство useGrouping):

Console.log((125452.32).toLocaleString(«ru-RU»,{useGrouping:true})); //»125 452,32″

Вывести с число с определённым количеством цифр (2) после запятой:

Console.log((1240.4564).toLocaleString(«ru-RU»,{minimumFractionDigits:2, maximumFractionDigits:2})); //»1 240,46″

Rounding vs Truncating #

The difference between these two methods is minor but very important to understand. Both of them are methods of approximating a number by dropping decimal places. Rounding approximates a number using a nearby number at a given degree of accuracy. It can occur in two directions: up and down. Rounding up approximates a number towards positive infinity. Rounding down towards negative infinity. Truncating approximates without rounding. In other words, it “rounds” towards zero.

Hopefully you get the difference. It makes truncating rarely useful in precise calculations (although JavaScript probably isn’t a good choice at all if you need precise calculations) but you can come across a situation when it may be irreplaceable. Once example can be when needing to drop decimal places from a pixel value to avoid anti aliasing or weird pixel rounding which is completely different across browser engines.

Сравнение дробных чисел

У математических вычислений есть одна особенность — их результат не всегда абсолютно точный. Это проблема
не только JavaScript, но и большинства языков программирования. Так происходит потому, что числа и другие
данные переводятся в двоичный код, и только потом с ними производятся вычисления.

В большинстве случаев это
не приводит к особенным трудностям, просто в результате расчётов иногда получается число с большим количеством
знаков после запятой. Но есть ситуация, когда неточность вычислений влияет на работу программы. Это сравнение
чисел. Если сравниваются разные числа, то здесь всё будет нормально.

5.1 < 5.2

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

Округление с помощью эпсилона

Альтернативный метод 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. Но если необходимо обеспечить поддержку в старых браузерах, то нужно использовать полифиллы.

Как явно преобразовать строку в число?

Явно привести строку в число можно посредством следующих способов:

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).

Функция 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.

Сравнение дробных чисел

У математических вычислений есть одна особенность — их результат не всегда абсолютно точный. Это проблема
не только JavaScript, но и большинства языков программирования. Так происходит потому, что числа и другие
данные переводятся в двоичный код, и только потом с ними производятся вычисления. В большинстве случаев это
не приводит к особенным трудностям, просто в результате расчётов иногда получается число с большим количеством
знаков после запятой. Но есть ситуация, когда неточность вычислений влияет на работу программы. Это сравнение
чисел. Если сравниваются разные числа, то здесь всё должно быть нормально.

5.1

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

Round() в Go 1.10

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

Похоже, что мы берём битовое представление числа, сдвигаем его и применяем маску. Согласно :

Рассматривая приведённые выше константы, мы видим, что сдвиг составляет 64 — 11 — 1, что означает 64 бита на число, 11 из которых используются для показателя степени, один — для знака и 52 оставшихся бита — для мантиссы. Это означает, что используемый сдвиг удаляет биты мантиссы, а маска удаляет бит знака, оставляя нас только с показателем степени.

В полученном числе показатель степени записан не как он есть, а с прибавлением числа 1023 (это делается для того чтобы записывать отрицательные показатели для очень маленьких чисел), что означает, что мы должны вычесть 1023 из e, вычисленного выше, чтобы получить фактический показатель. Иными словами, если e < bias, то мы имеем отрицательный показатель степени, что означает, что абсолютное значение float должно быть < 1. Действительно, дальше мы видим:

Здесь бит маскируется знаковым битом, это используется только для сохранения правильного знака: теперь мы можем полностью игнорировать мантиссу. Мы можем это сделать, потому что в этом случае нас интересует только показатель степени. Так как используется основание степени 2, а e < bias, мы знаем, что наименьший показатель, который может быть, равен -1, а 2 ^ -1 = 0,5. Кроме того, мантисса имеет некоторое значение 1.X. Таким образом, в зависимости от показателя наше число находится либо в диапазоне (0,5, 1), либо в диапазоне (0, 0,5). Поэтому во втором случае для правильного округления нам нужно добавить к числу единицу. Фух. Подробнее это описано в википедии.

Теперь разберём второй случай:

Наверное, вы думаете, что условие в этой ветке должно быть e > bias, чтобы покрыть все случаи с положительным показателем степени. Но вместо этого тут используется только их часть. Использование сдвига здесь особенно интересно, потому что кажется, что оно несравнимо с bias. Первое — это число битов смещения, а второе — численное смещение. Но, поскольку числа с плавающей точкой представлены как (1.мантисса) * 2 ^ X, то если X больше числа битов в мантиссе, мы гарантированно получим значение без дробной части. То есть показатель степени сместил десятичную точку вправо настолько, что мантисса окончательно пропала. Таким образом, выражение в этой ветке игнорирует числа с плавающей точкой, которые уже округлены.

Первая строка тут простая: вычитаем bias из e и получаем реальное значение показателя степени. Вторая строка добавляет к значению 0,5. Это работает, потому что старший бит мантиссы добавляет 0,5 к финальной сумме (см. представление в статье “Википедии” ниже). В этом случае эта сумма переполняет 52-битные границы мантиссы, показатель степени будет увеличен на 1. Значение показателя степени не сможет переполниться до знакового бита, так как оно не может быть больше bias+shift из примера выше. В любом случае, дробная часть очищается. Таким образом, если дробная часть была больше или равна 0,5, она будет увеличена на 1, в противном случае будет отброшена. Хитро и не очевидно до тех пор, пока мы не посмотрим глубже.

Целая и дробная часть числа

Получить целую часть числа можно используя метод Math.floor() и parseInt() :

Console.log(Math.floor(7.21)); // 7
console.log(parseInt(7.21)); // 7

Получить дробную часть числа можно воспользовавшимся оператором процент (%). Данный оператор возвращает остаток, который будет получен от деления первого числа на второе. В данном случае в качестве 2 числа необходимо использовать 1.

Console.log(7.21%1); // 0.20999999999999996
// с точностью до 2 знаков после запятой
console.log((7.21%1).toFixed(2)); // «0.21»

Кроме этого дробную часть можно получить также с помощью вычислений:

Var number = 7.21;
var fractionNumber = number — Math.floor(Math.abs(number));
console.log(fractionNumber); // 0.20999999999999996

Делится ли число нацело

Определить делится ли число нацело можно используя оператор процента:

Var number = 9;
// если остаток от деления числа number на 3 равен 0, то да, иначе нет
if (number%3==0) {
console.log («Число » + number + » делится на 3″);
} else {
console.log («Число » + number + » не делится на 3″);
}

Еще немного методов

В JavaScript также есть и другие 2 метода, которые занимаются округлением числовых представлений. Однако они несколько отличаются.

Речь пойдет о таких инструментах, как toFixed ()
и toPrecision ()
. Они отвечают не просто за округление, а за ее точность до определенных знаков. Давайте покопаем глубже.

toFixed ()

С помощью данного механизма можно указывать, до скольких знаков после запятой нужно округлить значение. Метод возвращает результат в виде строки. Ниже я прикрепил вариант с тремя разными вариантами. Проанализируйте полученные ответы.

Как видно, если не указать аргумента, то toFixed ()) округлит дробное значение до целого
числа. В третьей строке выполнено округление до 2-знаков,
а в четвертой – из-за параметра «7» было дописано еще три 0.

toPrecision ()

Данный метод действует несколько иначе. На месте аргумента можно оставить как пустое место, так и установить параметр. Однако последний будет округлять числа до указанного количества цифр, не обращая внимания на запятую. Вот какие результаты выдала программа, переписанная с прошлого примера:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector