Apakah ini angka?

17

Pendahuluan:

Saya ingin melatih membuat test case, jadi saya akan mencobanya dengan mudah.

Tantangan:

Ambil input (string) apa saja (dalam rentang ASCII yang terlihat) dan simpulkan jika itu adalah angka dan hasilkan sesuatu yang dapat digunakan untuk mengevaluasi.

Aturan:

  • Angka hanya akan berisi karakter -0123456789,.
  • Jawaban hanya diperlukan untuk mengenali angka antara -1000000000 dan 1000000000 (eksklusif), tetapi dapat mengenali angka besar secara sewenang-wenang.
  • Anda dapat menulis program atau fungsi lengkap.
  • Jika suatu angka, kembalikan apa pun yang dapat digunakan untuk membedakannya dan mendokumentasikan output dalam deskripsi (mis. My program outputs T if a number, F if not.).
  • Input akan berupa jumlah karakter apa pun dalam rentang ASCII atau kosong (jika kosong mengembalikan apa pun yang Anda hasilkan jika bukan angka).
  • Angka bisa termasuk titik desimal (mis. 3.14). Jika ya, mereka harus memiliki setidaknya satu digit sebelum titik desimal dan setidaknya satu setelahnya.
  • Angka bisa memiliki nol di depan atau di belakang (mis. 000001.00000).
  • Bagian integer dari angka dapat dibagi untuk dibaca menjadi potongan tiga digit dengan koma (mis. 1,000.23456). Dalam hal ini mereka harus dibagi setiap tiga digit dari kanan ke kiri (ex. 1,234,567, 10,000.202, 123,234.00, 0,123.293).
  • Angka negatif ditunjukkan oleh pemimpin -(mis. -1.23). Arahan +untuk menunjukkan angka positif tidak diizinkan, dan harus menghasilkan output palsu.
  • Pengecualian TIDAK dihitung sebagai output yang valid dan dapat dilihat (kecuali ketika mereka dapat meneruskan output ke stream out standar (mis. Exception on line N [...]Dapat dimasukkan sebagai output untuk nomor / bukan nomor jika string dimasukkan ke stream out standar.

Kasus uji:

(dengan asumsi My program outputs T if a number, F if not.versinya)

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]

, karakter paling tidak adalah pemenangnya.

n4melyh4xor
sumber
Bisakah kita menganggap input selalu ASCII?
Brad Gilbert b2gills
@ BradGilbertb2gills, ya.
n4melyh4xor atau
Jika -123OK, bagaimana dengan +456-> baik atau buruk. Atau tidak ikut serta +dalam pesta?
chux - Reinstate Monica
@ chux, kereta pesta berangkat sebelum + tiba di sana. Semoga beruntung lain kali, +.
n4melyh4xor atau
2
Saat orang meminta klarifikasi dalam komentar, Anda harus mengedit pertanyaan. Seharusnya tidak perlu membaca komentar untuk mengetahui spesifikasi. Saya telah mengedit untuk menyertakan jawaban dan beberapa kasus uji.
Peter Taylor

Jawaban:

10

Retina , 28 29 31 40 34 byte

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

Keluaran 1jika benar, 0sebaliknya. Sejauh yang saya mengerti, dalam hal ini Retina menampilkan jumlah kecocokan yang dimiliki regex pada input.

Cobalah online!

Test Suite

Suntingan

  • Diperbaiki untuk mematuhi aturan "harus ada angka setelah tempat desimal"
  • Diperbaiki untuk mematuhi aturan "pegangan negatif"
  • Diperbaiki untuk mematuhi pemisah koma opsional
  • Memperbaiki bug dengan ribuan pemisah seperti yang dicatat oleh @MartinEnder
  • Golf dengan menghapus lookahead bersyarat

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
sumber
@MartinEnder Diperbaiki! Juga, bagaimana Anda menentukan bendera (misalkan bendera untuk mdan g) di Retina?
Kritixi Lithos
Letakkan a `di depan regex, dan kemudian pengubah pergi di depannya, misalnya m`^.$. gtidak ada di .NET, kecocokan bersifat global secara default.
Martin Ender
3

JavaScript, 46 49 byte

Ini adalah port langsung dari jawaban Retina saya. Satu-satunya alasan saya menggunakan JS adalah agar ada cara mudah untuk menguji regex menggunakan Snack Snippet di bawah ini

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
sumber
Jika bukan karena beberapa aturan (seperti aturan koma), seseorang bisa melakukannya isNaN(+prompt())untuk 16 karakter. Begitulah hidup, saya kira
Matheus Avellar
2

Perl 6 , 42 byte

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

Cobalah

Diperluas:

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

PHP, 62 byte

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

Builtin tidak dapat menangani koma dan menerima notasi ilmiah; jadi saya harus berjalan di jalan regex. <?=is_numeric($argv[1]);akan menjadi 24 byte.

Titus
sumber
0

alat bash / Unix, 64 byte

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

Simpan ini sebagai file, dan berikan string untuk diuji sebagai argumen pertama ke perintah.

Output adalah 0 untuk non-angka, 1 untuk angka.

Jika Anda bersedia menerima input dari stdin dan jika Anda dapat menjamin bahwa input hanya terdiri dari satu baris, maka Anda dapat menghapus <<< "$ 1" di bagian akhir, menghasilkan 57 byte .

Adapun kode itu sendiri, opsi -c untuk egrep menghitung jumlah baris yang cocok (yang akan 0 atau 1).

Mitchell Spector
sumber
0

Pyth, 25 karakter

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

Mengompresi regex Kritixi Lithos .

Cobalah online. Menggunakan karakter Unicode di luar Basic Multilingual Plane, yang TIO tampaknya tidak bisa atasi? Aplikasi kecil ini melaporkan ukuran yang salah untuk string. Penghitung karakter / byte ini membuatnya benar.

Lynn
sumber
0

C89, 195 byte

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

Tidak Disatukan:

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;
}
kucing
sumber
0

Python 2, 79 byte

Solusi 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

Cobalah online

Possum Mati
sumber
0

c #, 75 byte

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