Блог Конфуция
Округляем 05.06.2009

Сколько способов отбросить дробную часть числа есть в яваскрипте?


var t = 36.6
Math.floor(t)
parseInt(t)
t - t % 1
t & -1
+/^-?\d+/.exec(t)
+t.toFixed()
t >> 0
//=> 36

UPD 2009-09-23: Александр Тармолов подзсказал метод Number#toFixed(), огромное ему спасибо — буду тестить :)

UPD 2010-01-14: придумалось еще t >> 0

Для отрицательного числа floor() подходит не очень, а & -1 — для чисел больше десяти миллионов. Но в том-то и прелесть, что всегда можно выбрать подходящий вариант.

Тестим

Интересно, а как сильно тормозит каждый из вариантов?


(function(){
console.time('empty')
for (var i = 0.5; i < 100000; i++);
console.timeEnd('empty')
})();
//=> 1ms


(function(){
var f = Math.floor
console.time('floor')
for (var i = 0.5; i < 100000; i++)
	f(i)
console.timeEnd('floor')
})();
//=> 1ms (round() и ceil() дают то же)

(function(){
console.time('Math.floor:Math.ceil')
for (var i = 0.5; i < 100000; i++)
	i >= 0 ? Math.floor(i) : Math.ceil(i)
console.timeEnd('Math.floor:Math.ceil')
})();
//=> 36ms


(function(){
var f = Math.floor, c = Math.ceil
console.time('var floor:ceil')
for (var i = 0.5; i < 100000; i++)
	i >= 0 ? f(i) : c(i)
console.timeEnd('var floor:ceil')
})();
//=> 1ms


(function(){
console.time('parseInt')
for (var i = 0.5; i < 100000; i++)
	parseInt(i)
console.timeEnd('parseInt')
})();
//=> 162ms


(function(){
var f = parseInt
console.time('var parseInt')
for (var i = 0.5; i < 100000; i++)
	f(i)
console.timeEnd('var parseInt')
})();
//=> 1ms


(function(){
console.time('%')
for (var i = 0.5; i < 100000; i++)
	i - i % 1
console.timeEnd('%')
})();
//=> 3ms


(function(){
console.time('&')
for (var i = 0.5; i < 100000; i++)
	i & -1
console.timeEnd('&')
})();
//=> 1ms


(function(){
console.time('>>')
for (var i = 0.5; i < 100000; i++)
	i >> 0
console.timeEnd('>>')
})();
//=> 1ms


(function(){
var rex = /^-?\d+/
console.time('toFixed')
for (var i = 0.5; i < 100000; i++)
	+i.toFixed()
console.timeEnd('toFixed')
})();
//>>> 83ms


(function(){
console.time('rex')
for (var i = 0.5; i < 100000; i++)
	+/^-?\d+/.exec(i)
console.timeEnd('rex')
})();
//=> 1100ms


(function(){
var rex = /^-?\d+/
console.time('cached rex')
for (var i = 0.5; i < 100000; i++)
	+rex.exec(i)
console.timeEnd('cached rex')
})();
//=> 1111ms

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

Ах, да, результаты для фаерфокса 3.5.7 на Core 2 Duo 2,66 ГГц 6 Мб.

Теги:
  • клиент
  • benchmark
  • int
  • javascript
  • round
Очень жду ваших комментариев на почту или на гитхаб.