这是数字吗?


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,56710,000.202123,234.000,123.293)。
  • 负数由前导-(例如-1.23)表示。领先+以指示正数是不允许的,并且会导致在falsy输出。
  • 异常不算作有效且可辨别的输出(除非它们可以将输出传递到标准输出流(例如,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 '16

@ BradGilbertb2gills,是的。
n4melyh4xor或2016年

如果-123可以,那么+456->好还是坏。还是被+排除在派对之外?
chux-恢复莫妮卡

@chux,在+到达之前离开的派对火车。下次运气更好,+。
n4melyh4xor或2016年

2
当人们要求对注释进行澄清时,您应该编辑问题。永远不必为了了解规格而阅读注释。我进行了编辑,以包括答案和一些测试用例。
彼得·泰勒

Answers:


10

视网膜28 29 31 40 34字节

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

1如果为真,0则输出,否则为。据我了解,在这种情况下,视网膜输出正则表达式在输入中具有的匹配项数。

在线尝试!

测试套件

编辑

  • 固定为符合“小数点后应该有数字”规则
  • 固定以符合“处理否定”规则
  • 固定以符合可选的逗号分隔符
  • 修复了@MartinEnder指出的带有数千个分隔符的错误
  • 通过取消条件超前来打高尔夫球

正则说明

^-?\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固定!另外,如何在Retina中指定标志(例如m和的标志g)?
Kritixi Lithos

`在正则表达式前放置一个,然后将修饰符放在该正则表达式之前,例如m`^.$g在.NET中不存在,默认情况下匹配是全局的。
马丁·恩德

3

JavaScript,46 49字节

这是我的视网膜答案的直接入口。我使用JS的唯一原因是使用下面的Snack 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个字符即可。我想这就是生活
Matheus Avellar '17

2

Perl 6,42个字节

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

尝试一下

展开:

{  # 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个字节

至于代码本身,egrep的-c选项对匹配的行数进行计数(将为0或1)。



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;}

取消高尔夫:

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;
}

0

Python 2,79字节

正则表达式解决方案

import re
lambda s:[s]==re.findall('-?(?:\d{1,3}(?:,\d{3}\d+)(?:\.?\d+)?',s)


-?                                          | Starts with 0-1 dashes
  (?:\d{1,3}(?:,\d{3})+                     | Have 1-3 digits and 1+ (comma followed by 3 digits)
                       |\d+)                | or 1+ digits
                            (?:\.?\d+)?     | Ends with dot and 1+ digits or nothing

在线尝试


0

c#,75个字节

bool t(string n){double v;return double.TryParse(n.Replace(",",""),out v);}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.