Ist das eine Nummer?

17

Auftakt:

Ich wollte üben, Testfälle zu machen, also werde ich sie an etwas Einfachem ausprobieren.

Herausforderung:

Nehmen Sie eine beliebige (String-) Eingabe (innerhalb des sichtbaren ASCII-Bereichs) und schließen Sie daraus, ob es sich um eine Zahl handelt, und geben Sie etwas aus, das zur Auswertung verwendet werden könnte.

Regeln:

  • Eine Zahl enthält nur die Zeichen -0123456789,.
  • Antworten sind nur erforderlich, um Zahlen zwischen -1000000000 und 1000000000 (exklusiv) zu erkennen, können jedoch beliebig große Zahlen erkennen.
  • Sie können ein vollständiges Programm oder eine Funktion schreiben.
  • Wenn eine Zahl vorhanden ist, geben Sie alles zurück, was zum Erkennen der Zahl verwendet werden könnte, und dokumentieren Sie die Ausgabe in der Beschreibung (z. B. My program outputs T if a number, F if not. ).
  • Die Eingabe ist eine beliebige Anzahl von Zeichen innerhalb des ASCII-Bereichs oder leer (wenn leer, geben Sie alles zurück, was Sie ausgeben würden, wenn keine Zahl).
  • Zahlen können einen Dezimalpunkt enthalten (z. B. 3.14 ). In diesem Fall müssen sie mindestens eine Ziffer vor dem Komma und mindestens eine nach dem Komma haben.
  • Zahlen können führende oder nachfolgende Nullen haben (z. 000001.00000 ).
  • Der ganzzahlige Teil einer Zahl kann zur besseren Lesbarkeit in dreistellige Abschnitte mit Kommas (z. B.) unterteilt werden 1,000.23456. In diesem Fall müssen sie alle drei Ziffern von rechts nach links unterteilt werden (ex. 1,234,567, 10,000.202, 123,234.00, 0,123.293).
  • Negative Zahlen werden durch ein vorangestelltes -(z. B. -1.23) gekennzeichnet. Ein +Anführungszeichen zur Angabe einer positiven Zahl ist nicht zulässig und sollte zu einer falschen Ausgabe führen.
  • Ausnahmen werden NICHT als gültige und erkennbare Ausgabe gezählt (es sei denn, sie können Ausgaben an den Standard-Out-Stream übergeben (z. Exception on line N [...]B. können als Ausgabe für eine Zahl / Nichtzahl eingegeben werden, wenn die Zeichenfolge an den Standard-Out-Stream übergeben wird).

Testfälle:

(unter der Annahme der My program outputs T if a number, F if not.Version)

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]

, am wenigsten Zeichen ist der Gewinner.

n4melyh4xor
quelle
Können wir annehmen, dass die Eingabe immer ASCII ist?
Brad Gilbert b2gills
@ BradGilbertb2gills, ja.
n4melyh4xor
Wenn -123es in Ordnung ist, was ist mit +456-> gut oder schlecht. Oder ist +von der Party ausgeschlossen?
chux - Wiedereinsetzung von Monica
@chux, der Partyzug fuhr ab, bevor der + dort ankam. Viel Glück beim nächsten Mal, +.
n4melyh4xor
2
Wenn Leute in Kommentaren um Erläuterungen bitten, sollten Sie die Frage bearbeiten. Es sollte niemals notwendig sein, die Kommentare zu lesen, um die Spezifikation zu kennen. Ich habe bearbeitet, um die Antworten und einige Testfälle einzuschließen.
Peter Taylor

Antworten:

10

Retina , 28 29 31 40 34 Bytes

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

Ausgänge 1wenn truthy, 0anders. Soweit ich weiß, gibt Retina in diesem Fall die Anzahl der Übereinstimmungen aus, die der Regex für die Eingabe hat.

Probieren Sie es online!

Test Suite

Bearbeitungen

  • Behoben, um der Regel "Nach dem Komma sollte es Ziffern geben" zu entsprechen
  • Korrigiert, um den Regeln zum Behandeln von Negativen zu entsprechen
  • Korrigiert, um den optionalen Kommatrennzeichen zu entsprechen
  • Fehler mit Tausendertrennzeichen behoben, wie von @MartinEnder festgestellt
  • Golfen durch Entfernen des bedingten Lookahead

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)
Kritixi Lithos
quelle
@MartinEnder behoben! Wie legen Sie die Flags (z. B. Flags für mund g) in der Netzhaut fest?
Kritixi Lithos
Setzen Sie ein `vor den regulären Ausdruck, und dann gehen die Modifikatoren davor, z m`^.$. gexistiert in .NET nicht, Übereinstimmungen sind standardmäßig global.
Martin Ender
3

JavaScript, 46 49 Bytes

Dies ist ein direkter Port meiner Retina-Antwort. Der einzige Grund, warum ich JS verwendet habe, ist, dass es eine einfache Möglichkeit gibt, den regulären Ausdruck mit dem folgenden Snack-Snippet zu testen

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
quelle
Wenn es nicht für einige Regeln (wie die Komma-Regel) wäre, könnte man einfach isNaN(+prompt())für 16 Zeichen tun . So ist das Leben, nehme ich an
Matheus Avellar
2

Perl 6 , 42 Bytes

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

Versuch es

Erweitert:

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

PHP, 62 Bytes

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

Das Builtin kann keine Kommas verarbeiten und akzeptiert die wissenschaftliche Notation. also musste ich den regulären Weg gehen. <?=is_numeric($argv[1]);wäre 24 Bytes gewesen.

Titus
quelle
0

Bash / Unix-Tools, 64 Byte

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

Speichern Sie dies als Datei und übergeben Sie die zu testende Zeichenfolge als erstes Argument an den Befehl.

Die Ausgabe ist 0 für eine Nicht-Nummer, 1 für eine Nummer.

Wenn Sie bereit sind, Eingaben von stdin zu akzeptieren und wenn Sie garantieren können, dass die Eingabe nur aus einer Zeile besteht, können Sie die <<< "$ 1" am Ende entfernen, was 57 Byte ergibt .

Was den Code selbst betrifft, zählt die Option -c, um egrep zu erstellen, die Anzahl der übereinstimmenden Zeilen (die entweder 0 oder 1 sein werden).

Mitchell Spector
quelle
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;}

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;
}
Katze
quelle
0

Python 2, 79 Bytes

Regex-Lösung

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

Probieren Sie es online aus

Totes Opossum
quelle
0

c #, 75 bytes

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