¿Es este un número?

17

Preludio:

Quería entrenar haciendo casos de prueba, así que los probaré en algo fácil.

Desafío:

Tome cualquier entrada (cadena) dada (dentro del rango ASCII visible) y deduzca si es un número y genere algo que pueda usarse para evaluar.

Reglas:

  • Un número solo contendrá los caracteres -0123456789,.
  • Las respuestas solo son necesarias para reconocer números entre -1000000000 y 1000000000 (exclusivo), pero pueden reconocer números arbitrariamente grandes.
  • Puede escribir un programa completo o una función.
  • Si es un número, devuelva cualquier cosa que pueda usarse para discernirlo y documente el resultado en la descripción (ej. My program outputs T if a number, F if not.).
  • La entrada será cualquier cantidad de caracteres dentro del rango ASCII o vacía (si está vacía, devuelve lo que haya generado si no es un número).
  • Los números pueden incluir un punto decimal (ej. 3.14). Si lo hacen, deben tener al menos un dígito antes del punto decimal y al menos uno después.
  • Los números pueden tener ceros iniciales o finales (ej. 000001.00000).
  • La parte entera de un número podría dividirse para facilitar su lectura en trozos de tres dígitos con comas (ej. 1,000.23456). En este caso deberán ser divididos cada tres dígitos de derecha a izquierda (ej. 1,234,567, 10,000.202, 123,234.00, 0,123.293).
  • Los números negativos se indican con un interlineado -(ej. -1.23). Un líder +para indicar un número positivo no está permitido, y debe dar lugar a la salida Falsy.
  • Las excepciones NO se cuentan como salida válida y discernible (excepto cuando pueden pasar salidas a la secuencia de salida estándar (p. Ej., Exception on line N [...]Pueden ingresarse como salida para un número / no número si la cadena se coloca en la secuencia de salida estándar).

Casos de prueba:

(asumiendo la My program outputs T if a number, F if not.versión)

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]

, menos personajes es el ganador.

n4melyh4xor
fuente
¿Podemos suponer que la entrada es siempre ASCII?
Brad Gilbert b2gills
@ BradGilbertb2gills, sí.
n4melyh4xor
Si -123está bien, ¿qué pasa con +456-> bueno o malo? ¿O +queda fuera de la fiesta?
chux - Restablecer Monica
@chux, el tren de la fiesta se fue antes de que llegara el +. Mejor suerte la próxima vez, +.
n4melyh4xor
2
Cuando las personas solicitan aclaraciones en los comentarios, debe editar la pregunta. Nunca debería ser necesario leer los comentarios para conocer las especificaciones. He editado para incluir las respuestas y algunos casos de prueba.
Peter Taylor

Respuestas:

10

Retina , 28 29 31 40 34 bytes

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

Salidas 1si son verdaderas, de lo 0contrario. Por lo que entiendo, en este caso Retina emite el número de coincidencias que la expresión regular tiene en la entrada.

Pruébalo en línea!

Banco de pruebas

Ediciones

  • Se corrigió para cumplir con la regla "debería haber dígitos después del lugar decimal"
  • Solucionado para cumplir con las reglas de "manejar negativos"
  • Solucionado para cumplir con los separadores de coma opcionales
  • Se corrigió un error con miles de separadores como lo señaló @MartinEnder
  • Golfed mediante la eliminación anticipada condicional

Explicación

^-?\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)
Kritixi Lithos
fuente
@MartinEnder fijo! Además, ¿cómo se especifican las banderas (digamos banderas para my g) en Retina?
Kritixi Lithos
Coloque un `frente a la expresión regular, y luego los modificadores van delante de eso, por ejemplo m`^.$. gno existe en .NET, las coincidencias son globales de forma predeterminada.
Martin Ender
3

JavaScript 46 49 bytes

Este es un puerto directo de mi respuesta Retina. La única razón por la que usé JS es para que haya una manera fácil de probar la expresión regular utilizando el Snack Snippet a continuación

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>

Kritixi Lithos
fuente
Si no fuera por algunas de las reglas (como la regla de coma), uno podría simplemente hacer isNaN(+prompt())16 caracteres. Así es la vida, supongo
Matheus Avellar
2

Perl 6 , 42 bytes

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

Intentalo

Expandido:

{  # 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

  /
}
Brad Gilbert b2gills
fuente
1

PHP, 62 bytes

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

La construcción no puede manejar comas y acepta notación científica; así que tuve que caminar por la expresión regular. <?=is_numeric($argv[1]);habría sido de 24 bytes.

Tito
fuente
0

herramientas bash / Unix, 64 bytes

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

Guarde esto como un archivo y pase la cadena que se probará como el primer argumento para el comando.

La salida es 0 para un no número, 1 para un número.

Si está dispuesto a aceptar la entrada de stdin y puede garantizar que la entrada consta de una sola línea, puede eliminar el <<< "$ 1" al final, lo que resulta en 57 bytes .

En cuanto al código en sí, la opción -c para egrep cuenta el número de líneas coincidentes (que serán 0 o 1).

Mitchell Spector
fuente
0

C89, 195 bytes

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

Sin golf:

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;
}
gato
fuente
0

Python 2, 79 bytes

Solución Regex

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

Pruébalo en línea

Zarigüeya muerta
fuente
0

c #, 75 bytes

bool t(string n){double v;return double.TryParse(n.Replace(",",""),out v);}
Johan du Toit
fuente