Czy to jest liczba?

17

Preludium:

Chciałem trenować tworzenie przypadków testowych, więc wypróbuję je na czymś łatwym.

Wyzwanie:

Weź dowolne dane wejściowe (łańcuchowe) (w widocznym zakresie ASCII) i wywnioskuj, czy jest to liczba, i wypisz coś, co można wykorzystać do oceny.

Zasady:

  • Liczba będzie zawierać tylko znaki -0123456789,.
  • Odpowiedzi są wymagane tylko w celu rozpoznania liczb od -1000000000 do 1000000000 (wyłącznie), ale mogą rozpoznać dowolnie duże liczby.
  • Możesz napisać pełny program lub funkcję.
  • Jeśli jest liczbą, zwróć wszystko, co mogłoby być użyte do jej rozpoznania i udokumentowania wyniku w opisie (np. My program outputs T if a number, F if not.).
  • Dane wejściowe będą zawierać dowolną liczbę znaków w zakresie ASCII lub puste (jeśli puste, zwróć wszystko, co wypiszesz, jeśli nie będzie liczbą).
  • Liczby mogą zawierać kropkę dziesiętną (np. 3.14). Jeśli tak, muszą mieć co najmniej jedną cyfrę przed kropką dziesiętną i co najmniej jedną po niej.
  • Liczby mogą mieć początkowe lub końcowe zera (np. 000001.00000).
  • Część całkowitą liczby można podzielić dla czytelności na fragmenty trzech cyfr za pomocą przecinków (np. 1,000.23456). W tym przypadku muszą być one podzielone co trzy cyfry od prawej do lewej (np. 1,234,567, 10,000.202, 123,234.00, 0,123.293).
  • Liczby ujemne są oznaczone wiodącym -(np. -1.23). Wiodący +aby wskazać liczbę dodatnią nie jest dozwolona i powinna doprowadzić do wyjścia falsy.
  • Wyjątki NIE są liczone jako prawidłowe i rozpoznawalne dane wyjściowe (z wyjątkiem sytuacji, gdy mogą przekazać dane wyjściowe do standardowego strumienia wyjściowego (np. Exception on line N [...]Mogą zostać wprowadzone jako dane wyjściowe dla liczby / liczby innej, jeśli ciąg znaków zostanie umieszczony w standardowym strumieniu wyjściowym).

Przypadki testowe:

(przy założeniu My program outputs T if a number, F if not.wersji)

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]

, najmniej znaków jest zwycięzcą.

n4melyh4xor
źródło
Czy możemy założyć, że dane wejściowe to zawsze ASCII?
Brad Gilbert b2gills,
@ BradGilbertb2gills, tak.
n4melyh4xor
Jeśli -123jest OK, co z +456-> dobrym lub złym. Czy jest +wykluczony z imprezy?
chux - Przywróć Monikę
@chux, pociąg imprezowy wyjechał przed +. Powodzenia następnym razem, +.
n4melyh4xor
2
Gdy ludzie proszą o wyjaśnienia w komentarzach, należy edytować pytanie. Nigdy nie powinno być konieczne czytanie komentarzy w celu poznania specyfikacji. Zredagowałem, aby uwzględnić odpowiedzi i niektóre przypadki testowe.
Peter Taylor,

Odpowiedzi:

10

Retina , 28 29 31 40 34 bajtów

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

Wyprowadza, 1jeśli to prawda, w 0przeciwnym razie. O ile rozumiem, w tym przypadku Retina wypisuje liczbę dopasowań wyrażeń regularnych na wejściu.

Wypróbuj online!

Pakiet testowy

Edycje

  • Naprawiono, aby zachować zgodność z zasadą „powinny być cyfry po przecinku”
  • Naprawiono, aby zachować zgodność z zasadami „obsługiwać negatywy”
  • Naprawiono, aby zachować zgodność z opcjonalnymi separatorami przecinków
  • Naprawiono błąd z tysiącami separatorów, jak zauważył @MartinEnder
  • Grał w golfa, usuwając warunkowy 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
źródło
@MartinEnder Naprawiono! Ponadto, jak określasz flagi (powiedz flagi dla mi g) w Retina?
Kritixi Lithos,
Umieść `przed wyrażeniem regularnym, a następnie modyfikatory przed nim, np m`^.$. gnie istnieje w .NET, dopasowania są domyślnie globalne.
Martin Ender,
3

JavaScript, 46 49 bajtów

To jest bezpośredni port mojej odpowiedzi Retina. Jedynym powodem, dla którego użyłem JS, jest to, że istnieje łatwy sposób przetestowania wyrażenia regularnego za pomocą Snippet przekąski poniżej

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
źródło
Gdyby nie niektóre reguły (takie jak przecinek), można po prostu zrobić isNaN(+prompt())16 znaków. Takie jest życie, jak sądzę
Matheus Avellar
2

Perl 6 , 42 bajtów

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

Spróbuj

Rozszerzony:

{  # 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
źródło
1

PHP, 62 bajty

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

Wbudowane nie obsługuje przecinków i akceptuje notację naukową; więc musiałem przejść wyrażenie regularne. <?=is_numeric($argv[1]);byłoby 24 bajtów.

Tytus
źródło
0

narzędzia bash / Unix, 64 bajty

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

Zapisz to jako plik i przekaż ciąg do przetestowania jako pierwszy argument polecenia.

Dane wyjściowe to 0 dla liczby nieparzystej, 1 dla liczby.

Jeśli chcesz zaakceptować dane wejściowe ze standardowego wejścia i jeśli możesz zagwarantować, że dane wejściowe składają się tylko z jednej linii, możesz usunąć <<< „$ 1” na końcu, co daje 57 bajtów .

Jeśli chodzi o sam kod, opcja -c egrep zlicza liczbę pasujących linii (która będzie równa 0 lub 1).

Mitchell Spector
źródło
0

Pyth, 25 znaków

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

Kompresuje wyrażenie regularne Kritixi Lithos .

Wypróbuj online. Używa znaków Unicode poza podstawową płaszczyzną wielojęzyczną, z którymi TIO najwyraźniej nie jest w stanie sobie poradzić? Ta mała aplikacja zgłasza jednak nieprawidłowy rozmiar ciągu. Ten licznik znaków / bajtów dobrze to robi.

Lynn
źródło
0

C89, 195 bajtów

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

Nie golfowany:

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;
}
kot
źródło
0

Python 2, 79 bajtów

Rozwiązanie 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

Wypróbuj online

Dead Possum
źródło
0

c #, 75 bajtów

bool t(string n){double v;return double.TryParse(n.Replace(",",""),out v);}
Johan du Toit
źródło