Это число?


17

Прелюдия:

Я хотел научиться делать тестовые случаи, поэтому я собираюсь попробовать их на чем-нибудь простом.

Вызов:

Возьмите любой заданный (строковый) ввод (в пределах видимого диапазона ASCII) и определите, является ли это число, и выведите что-то, что можно использовать для оценки.

Правила:

  • Число будет содержать только символы -0123456789,.
  • Ответы требуются только для распознавания чисел от -1000000000 до 1000000000 (исключая), но могут распознавать произвольно большие числа.
  • Вы можете написать полную программу или функцию.
  • Если число, верните все, что можно было бы использовать, чтобы распознать его и документировать вывод в описании (например My program outputs T if a number, F if not.).
  • Ввод будет любым количеством символов в диапазоне ASCII или пустым (если пустое значение возвращает то, что вы выведите, если не число).
  • Числа могут включать десятичную точку (напр. 3.14). Если это так, у них должна быть хотя бы одна цифра перед десятичной запятой и хотя бы одна после нее.
  • Числа могут иметь начальные или конечные нули (например, 000001.00000 ).
  • Целая часть числа может быть разделена для удобства чтения на куски из трех цифр с запятыми (например 1,000.23456). В этом случае они должны быть разделены каждые три цифры справа налево (напр. 1,234,567, 10,000.202, 123,234.00, 0,123.293).
  • Отрицательные числа обозначены лидирующими символами -(напр. -1.23). Знак, +указывающий положительное число, не допускается и должен привести к ложному выводу.
  • Исключения НЕ считаются действительными и различимыми выходными данными (за исключением случаев, когда они могут передавать выходные данные в стандартный выходной поток (например, Exception on line N [...]могут быть вставлены в качестве выходных данных для числа / не числа), если строка помещена в стандартный выходной поток.

Тестовые случаи:

(при условии My program outputs T if a number, F if not.версии)

123 -> T [on integer]
-123 -> T [negative numbers need to be handled]
0 -> T [on zero]
123.456 -> T [on floating point]
123,456.789 -> T [on evenly divided by 3 digits with comas]
123456789 -> T [thousand separators are not required]
0000001.00000 -> T [on leading/trailing zeros]
00.00 -> T [on zero and leading/trailing zeros]
999999999.9999999999999999999999999999999999999999999999999999 -> T [on close to the maximum value]
-999999999.9999999999999999999999999999999999999999999999999999 -> T [on close to the minimum value]
 -> F [on empty]
lolz -> F [on non-number value]
n4melyh4xor -> F [on non-number with digits]
  1.2 -> F [on space-padded]
9.3 1.3 -> F [on anyhow separated multiple numbers]
1e5 -> F [no scientific notation]
50cl05e.buty3ts0f4r -> F [on input with letters obscuring the number]
1,2,3,4.5678 -> F [on badly readability-divided number]
1,234.5,678 -> F [on readability-divided floating point part]
.234 -> F [on no leading zero]
+1 -> F [no leading + sign]
1.234.3 -> F [only one decimal point]
12345,678 -> F [on separator stopping mid-way]

, минимум символов является победителем.


Можем ли мы предположить, что вход всегда ASCII?
Брэд Гилберт b2gills

@ BradGilbertb2gills, да.
n4melyh4xor

Если -123все в порядке, как насчет +456-> хорошо или плохо. Или +остался вне партии?
chux - Восстановить Монику

@chux, партийный поезд ушел до того, как туда попал +. Удачи в следующий раз, +.
n4melyh4xor

2
Когда люди просят разъяснений в комментариях, вы должны отредактировать вопрос. Никогда не нужно читать комментарии, чтобы узнать спецификацию. Я отредактировал, чтобы включить ответы и некоторые контрольные примеры.
Питер Тейлор

Ответы:


10

Retina , 28 29 31 40 34 байта

^-?\d{1,3}((,\d{3})*|\d*)(\.\d+)?$

Выводы, 1если правда, в 0противном случае. Насколько я понимаю, в этом случае Retina выводит количество совпадений, которые есть у регулярного выражения на входе.

Попробуйте онлайн!

Тестирование

Правки

  • Исправлено в соответствии с правилом «после десятичного знака должны быть цифры»
  • Исправлено, чтобы соответствовать правилам обработки негативов
  • Исправлено для соответствия дополнительным разделителям запятых
  • Исправлена ​​ошибка с разделителями тысяч, как отмечает @MartinEnder
  • Гольф, удалив условный взгляд

RegExplanation

^-?\d{1,3}((,\d{3})*|\d*)(\.\d+)?$
^                                $  This marks the start and end of regex
 -?                                 Optional hyphen for negative number
   \d{1,3}                          Matches between 1 and 3 digits
          (             )           Capturing group
           (,\d{3})*                 Matches at least zero of comma and three numbers (in the case of separators)
                    |                OR
                     \d*             Matches at least zero digits (in the case of no separators)
                        (\.\d+)?    Matches an optional . and at least one digit (for decimal numbers)

@MartinEnder Исправлено! Кроме того, как вы указываете флаги (скажем, флаги для mи g) в Retina?
Kritixi Lithos

Поместите `перед регулярным выражением, а затем перед этим идут модификаторы, например m`^.$. gне существует в .NET, по умолчанию совпадения глобальны.
Мартин Эндер

3

JavaScript, 46 49 байт

Это прямой порт моего ответа Retina. Единственная причина, по которой я использовал JS, заключается в том, что есть простой способ протестировать регулярное выражение, используя Snacket Snippet ниже

f=s=>/^-?\d{1,3}((,\d{3})*|\d*)(\.\d+)?$/.test(s)

f=s=>/^-?\d{1,3}((,\d{3})*|\d*)(\.\d+)?$/.test(s)
<input oninput=p.innerText=f(value)><p id=p></p>


Если бы не некоторые из правил (например, правило запятой), можно было бы просто сделать isNaN(+prompt())для 16 символов. Такова жизнь, я полагаю
Матеус

2

Perl 6 , 42 байта

{?/^\-?[\d**1..3[\,\d**3]+|\d+][\.\d+]?$/}

Попытайся

Expanded:

{  # bare block lambda with implicit parameter 「$_」

  ? # turn the following into a Bool result

  /  # match implicitly against 「$_」

    ^                 # beginning of string

    \- ?              # optional leading 「-」

    [

      \d ** 1..3      # 1 to 3 digits
      [
        \,            # comma
        \d ** 3       # three digits
      ]+              # repeat at least once

    |                 # or

      \d+             # at least one digit

    ]

    [ \. \d+ ]?       # 「.」 followed by at least one digit optionally

    $  # end of string

  /
}

1

PHP, 62 байта

<?=preg_match("#^-?(\d+|\d{1,3}(,\d{3})*)(\.\d+)?$",$argv[1]);

Встроенный не может обрабатывать запятые и принимает научные обозначения; поэтому мне пришлось идти по пути регулярных выражений. <?=is_numeric($argv[1]);было бы 24 байта.


0

инструменты bash / Unix, 64 байта

egrep -c '^-?([0-9]+|[0-9]{1,3}(,[0-9]{3})+)(\.[0-9]+)?$'<<<"$1"

Сохраните это как файл и передайте проверяемую строку в качестве первого аргумента команды.

Выходные данные равны 0 для не числа, 1 для числа.

Если вы готовы принять входные данные от stdin и можете гарантировать, что входные данные состоят только из одной строки, вы можете удалить <<< «$ 1» в конце, что приведет к 57 байтам. .

Что касается самого кода, опция -c для egrep подсчитывает количество совпадающих строк (которые будут либо 0, либо 1).


0

Pyth, 25 символов

:zCiCM"૧򡊪񛨮򶟉񠫊򆻛񓰚祥񯯏󪬡򢝉񁘍񲲂쪤"^T6

Сжимает регулярное выражение Kritixi Lithos .

Попробуйте онлайн. Использует символы Unicode вне базовой многоязычной плоскости, с которой TIO, очевидно, не может справиться? Это маленькое приложение сообщает о неправильном размере строки. Этот счетчик символов / байтов делает это правильно.


0

C89, 195 байт

b,d,c,i;f(char*s){b=*s;for(d=c=i=0;i++,*(s++),d+=*s=='.',c+=*s==',',b=c?i&(i%4!=3)&*s==','?0:b:b;)if(*s==45&!i);else if((*s==32)|(*s==46)|*s==43|!isdigit(*s)&*s!=46&*s!=44)||!(d-1))b=0;return b;}

Ungolfed:

bool is_base10_number (const char* const str) {

  if(!str[0])return false;

  size_t
    dpts = 0,
    cmas = 0;

  for (size_t i = 0; i < strlen(str); i++) {

    if ((str[i] == '-') && (!i)){
      continue;
    }

    if (
      (str[i] == ' ')
      || (str[0] == '.')
      || (str[0] == '+')
      ||
      (
        (!isdigit(str[i]))
        && (str[i] != '.')
        && (str[i] != ',')
      )
    ) {
      return false;
    }

    dpts += str[i] == '.';
    cmas += str[i] == ',';

    if (cmas) {
      if (i & ((i % 4) != 3) & str[i] == ',') {
        return false;
      }
    }

  }

  if (dpts > 1) { return false; }

  return true;
}


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.