Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как опознать число? (https://javascript.ru/forum/misc/4226-kak-opoznat-chislo.html)

Octane 03.07.2009 16:46

Как опознать число?
 
В продолжение темы «Как опознать RegExp»

Известно, что в JavaScript NaN (Not a Number) принадлежит типу number:

alert(typeof NaN);


Как распознать, что каждая переменная является любым числом, но не NaN и не Infinity, как должна выглядеть функция isNumber?

var a = NaN;
var b = 1;
var c = {};
var d = Infinity;

function isNumber(x) {
   // ...
}

alert([isNumber(a), isNumber(b), isNumber(c), isNumber(d)]);
// Должно быть: false, true, false, false

Kolyaj 03.07.2009 16:50

А бесконечности?

Riim 03.07.2009 16:51

Если не думая, то так: x < 0 || x > 0 || x == 0
причем вариант x < 0 || x > -1 не годится, т. к. null тоже будет числом.

Octane 03.07.2009 17:00

Цитата:

Сообщение от Kolyaj
А бесконечности?

Дополнил вопрос.

Riim, твой вариант не срабатывает с Infinity.

Kolyaj 03.07.2009 17:01

Я имел в виду их пропускать или нет?

Octane 03.07.2009 17:04

Цитата:

Сообщение от Kolyaj
Я имел в виду их пропускать или нет?

Да

Riim 03.07.2009 17:04

Octane,
то две "m" то одна "i", что за фигня?

Цитата:

Сообщение от Octane
твой вариант не срабатывает с Infinity.

Это легко поправить если надо. Я обычно Infinity не учитываю.

Kolyaj 03.07.2009 17:08

Т.е. isNumber(Number.NEGATIVE_INFINITY) должен быть true?

Octane 03.07.2009 17:08

Цитата:

Сообщение от Riim
то две "m" то одна "i", что за фигня?

Сорри, поправил.

Цитата:

Сообщение от Kolyaj
Т.е. isNumber(Number.NEGATIVE_INFINITY) должен быть true?

false

блин без бесконечности все красивее выходило :(

Kolyaj 03.07.2009 17:11

Понятно, пойду помолчу :)

Riim 03.07.2009 17:40

Зачем вообще учитывать Infinity ? Я понимаю NaN.

Kolyaj 03.07.2009 17:46

Ну помолчал и будя.

А в чем цимес? isFinite же есть. А если бесконечности должны быть числами, то isNaN есть.

Octane 03.07.2009 18:00

Да сбили меня этими Infinity :stop:

Вообще вырисовывался такой вариант:
var a = NaN;
var b = 1;
var c = {};
var d = Infinity;
 
function isNumber(x) {
   return ! isNaN(x * 1);
}
 
alert([isNumber(a), isNumber(b), isNumber(c), isNumber(d)]);

тут isNumber(Infinity) выдает true.

В итоге мы пришли к реализации функционала встроенной функции isFinite.

Kolyaj 03.07.2009 18:02

Интересней реализовать isNaN :)

Riim 03.07.2009 18:15

Мой вариант выдает те же результаты и работает быстрей.

Octane 03.07.2009 18:23

Riim, в твоем варианте есть ошибка:
function isNumber(x) {
	return x < 0 || x > 0 || x == 0;
}
alert(isNumber(false));


Цитата:

Сообщение от Riim
Мой вариант … работает быстрей.

Проверял?
function isNumber(x) {
	return ! isNaN(x * 1);
}

function isNumber1(x) {
	return x < 0 || x > 0 || x === 0;
}

var t1 = new Date().getTime(), i = 100000;

while (i--) {
	isNumber(NaN);
	isNumber(1);
	isNumber({});
}

t1 = new Date().getTime() - t1;

var t2 = new Date().getTime();

i = 100000;

while (i--) {
	isNumber1(NaN);
	isNumber1(1);
	isNumber1({});
}

t2 = new Date().getTime() - t2;

alert([t1, t2]);

Riim 03.07.2009 18:24

Опять две "m" :(

Kolyaj 03.07.2009 18:29

Octane,
кликай по нику, зачем его писать?

Riim 03.07.2009 18:29

На копейки, но быстрей (Chrome). Если тестировать только на числах (на практике эта функция в основном их будет принимать), то заметно быстрей.
Куски "x > 0" и "x < 0" можно поменять местами, т. к. на практике положительные числа будут чаще.

Riim 03.07.2009 18:32

Цитата:

Сообщение от Octane
в твоем варианте есть ошибка

И в твоем тоже: на null говорит, что это число.

Octane 03.07.2009 18:36

:blink: не знал, что:
alert(null * 1) // будет 0

Ушел читать спецификацию…

ZoNT 03.07.2009 18:37

[example run]function isNumber1(x) {
return x < 0 || x > 0 || x === 0;
}
alert(isNumber1('1'))[/example]

Riim 03.07.2009 18:51

Все варианты трудно учесть, да и смысла не вижу. Например, если функция должна принимать число и получает NaN, то это ошибка и притом вполне возможная, если же она получает, например массив, то это уже неадекватная ошибка. Я пишу код под себя и сам я так точно не ошибусь.
Для чисел я обрабатываю такие варианты: положительные/отрицательные числа, 0, null, undefined, NaN
Для не чисел: null, undefined и если нет, то даже typeof/instanceof часто можно не смотреть (тут в каждой ситуации нужно отдельно думать)
Этого вполне хватает что бы учесть все !адекватные! ошибки.
Предложенный мною вариант все, что мне нужно учитывает, и более быстрого я не вижу.

Zeroglif 03.07.2009 19:10

typeof x == 'number' && isFinite(x);

Octane 03.07.2009 19:20

Наверное, самый железный вариант:
var a = NaN;
var b = 1;
var c = {};
var d = Infinity;
var e = null;
 
function isNumber(x) {
	return Object.prototype.toString.call(x) == "[object Number]" && isFinite(x);
}

alert([isNumber(a), isNumber(b), isNumber(c), isNumber(d), isNumber(e)]);

x-yuri 04.07.2009 01:12

а
var a = NaN;
var b = 1;
var c = {};
var d = Infinity;
var e = null;
 
function isNumber(x) {
    return (typeof x == "number" || x instanceof Number) && isFinite(x);
}
 
alert([isNumber(a), isNumber(b), isNumber(c), isNumber(d), isNumber(e)]);

UPD: уже вижу недостатки, хоть они и не всегда актуальны


Часовой пояс GMT +3, время: 14:38.