Ответ 1
В ES5 и ранее используйте Math.pow
:
var result = Math.pow(10, precision);
var precision = 5;
var result = Math.pow(10, precision);
console.log(result);
Мне нужно создать целочисленное значение для определенной мощности (это не правильный термин, но в основном мне нужно создать 10, 100, 1000 и т.д.). "Мощность" будет указана как параметр функции. Я придумал решение, но MAN чувствует себя взломанным и неправильным. Я хотел бы узнать лучший способ, если есть один, может быть, тот, который не основан на строках? Кроме того, eval() не является вариантом.
Вот что я имею в это время:
function makeMultiplierBase(precision)
{
var numToParse = '1';
for(var i = 0; i < precision; i++)
{
numToParse += '0';
}
return parseFloat(numToParse);
}
Я также просто придумал это решение, отличное от строки, но все еще кажется взломанным из-за цикла:
function a(precision)
{
var tmp = 10;
for(var i = 1; i < precision; i++)
{
tmp *= 10;
}
return tmp;
}
Кстати, мне нужно было сделать это, чтобы создать метод округления для работы с валютой. Я использовал var formatted = Math.round(значение * 100)/100
но этот код показывался повсюду, и я хотел, чтобы метод выполнял округление до определенной точности, поэтому я создал этот
if(!Math.roundToPrecision)
{
Math.roundToPrecision = function(value, precision)
{
Guard.NotNull(value, 'value');
b = Math.pow(10, precision);
return Math.round(value * b) / b;
}
}
Думал, что я включу это здесь, поскольку это оказалось удобной уже.
В ES5 и ранее используйте Math.pow
:
var result = Math.pow(10, precision);
var precision = 5;
var result = Math.pow(10, precision);
console.log(result);
Почему бы и нет:
function precision(x) {
return Math.pow(10, x);
}
Это имеет тот же результат, что и ваша функция, но я все еще не понимаю приложение/намерение.
function makeMultiplierBase(precision,base){
return Math.pow(base||10,precision);
}
если все, что вам нужно сделать, это поднять 10 до разных мощностей или любую базу любой силы, почему бы не использовать встроенный Math.pow(10,power);
, если у вас нет особой необходимости объяснять, чтобы изобрести колесо
Для степеней при 10³³ и выше Math.pow()
может потерять точность. Например:
Math.pow(10, 33); //-> 1.0000000000000001e+33
Math.pow(10, 34); //-> 1.0000000000000001e+34
Math.pow(10, 35); //-> 1e+35
Math.pow(10, 36); //-> 1e+36
Math.pow(10, 37); //-> 1.0000000000000001e+37
Хотя это не повседневная проблема, с которой вы можете столкнуться в JavaScript, это может быть довольно неприятным в некоторых ситуациях, особенно с операторами сравнения. Одним из примеров является функция Google log10Floor()
из библиотеки Closure:
/**
* Returns the precise value of floor(log10(num)).
* Simpler implementations didn't work because of floating point rounding
* errors. For example
* <ul>
* <li>Math.floor(Math.log(num) / Math.LN10) is off by one for num == 1e+3.
* <li>Math.floor(Math.log(num) * Math.LOG10E) is off by one for num == 1e+15.
* <li>Math.floor(Math.log10(num)) is off by one for num == 1e+15 - 1.
* </ul>
* @param {number} num A floating point number.
* @return {number} Its logarithm to base 10 rounded down to the nearest
* integer if num > 0. -Infinity if num == 0. NaN if num < 0.
*/
goog.math.log10Floor = function(num) {
if (num > 0) {
var x = Math.round(Math.log(num) * Math.LOG10E);
return x - (Math.pow(10, x) > num);
}
return num == 0 ? -Infinity : NaN;
};
Если вы передадите мощность 10 выше 10³³, эта функция может вернуть неверный результат, потому что Math.pow(10, 33) > 1e33
имеет значение true
. Способ, которым я работал, заключается в том, чтобы использовать принудительное число Number, объединяя экспонента в "1e":
+'1e33' //-> 1e+33
+'1e34' //-> 1e+34
+'1e35' //-> 1e+35
+'1e36' //-> 1e+36
+'1e37' //-> 1e+37
И, фиксируя функцию log10Floor()
:
goog.math.log10Floor = function(num) {
if (num > 0) {
var x = Math.round(Math.log(num) * Math.LOG10E);
return x - (+('1e' + x) > num);
}
return num == 0 ? -Infinity : NaN;
};
Примечание: ошибка в библиотеке закрытия с тех пор была исправлена .
Я просто наткнулся на что-то, проходя через https://github.com/aecostas/huffman. Скомпилированный код (js) имеет строку
alphabet_next = sorted.slice(0, +(sorted.length - 1 - groupsize) + 1 || 9e9);
Если вы попытаетесь оценить 9e9 (на node и в консоли браузера), он даст вам 9000000000, который "9 * 10 ^ 9". Основываясь на этом, вы можете просто сделать снизу, чтобы получить 10-ю степень.
var n = 2;
eval("1e"+n); //outputs 100
EDIT: больше по экспоненциальной записи из http://www.2ality.com/2012/03/displaying-numbers.html.
Существует два десятичных обозначения, используемых JavaScript: фиксированная нотация [ "+" | "-" ] digit + [ "." цифра +] и экспоненциальная нотация [ "+" | "-" ] digit [ "." digit +] "e" [ "+" | "-" ] цифра + Примером экспоненциального обозначения является -1.37e + 2. Для вывода всегда есть точно одна цифра перед точкой, для ввода вы можете использовать более одной цифры. Экспоненциальная нотация интерпретируется следующим образом: Учитывая число в экспоненциальном обозначении: значимый экспонента. Значение этого числа значащий × 10 показатель. Следовательно, -1.37e + 2 представляет число -137.
Если вы не хотите думать о необходимости каждый раз вызывать функции, вы можете создать класс, который будет выполнять преобразование для вас.
class Decimal {
constructor(value = 0, scale = 4) {
this.intervalValue = value;
this.scale = scale;
}
get value() {
return this.intervalValue;
}
set value(value) {
this.intervalValue = Decimal.toDecimal(value, this.scale);
}
static toDecimal(val, scale) {
const factor = 10 ** scale;
return Math.round(val * factor) / factor;
}
}
Использование:
const d = new Decimal(0, 4);
d.value = 0.1 + 0.2; // 0.3
d.value = 0.3 - 0.2; // 0.1
d.value = 0.1 + 0.2 - 0.3; // 0
d.value = 5.551115123125783e-17; // 0
d.value = 1 / 9; // 0.1111
Конечно, когда речь идет о десятичной системе, есть предостережения:
d.value = 1/3 + 1/3 + 1/3; // 1
d.value -= 1/3; // 0.6667
d.value -= 1/3; // 0.3334
d.value -= 1/3; // 0.0001
В идеале вы хотели бы использовать высокий масштаб (например, 12), а затем конвертировать его, когда вам нужно представить или сохранить его где-нибудь. Лично я экспериментировал с созданием UInt8Array и пытался создать значение точности (очень похожее на тип десятичного числа SQL), но, поскольку Javascript не позволяет перегрузить операторы, он становится немного утомительным из-за невозможности использования базовых математических операторов (+
, -
, /
, *
) и используя вместо этого функции, такие как add()
, substract()
, mult()
. Для моих нужд это того не стоит.
Но если вам нужен такой уровень точности и вы готовы выдержать использование функций для математики, то я рекомендую библиотеку decimal.js.
Используйте таблицу поиска. Но если это для округления сумм валют, вы должны использовать BigDecimal вместо всего schemozzle.