Ankieta - valid int

0

Piszę właśnie lekką bibliotekę do wyrażeń regularnych i mam problem.

Według kolegów, natrafia się czasem wyrażenie regularne którego cześć (grupa - capturing group) ma być tylko liczbą, chciałbym wtedy żeby użytkownicy tej biblioteki nie musieli się martwić parsowaniem. Wszyscy wiemy że PHP ma swoje smaczki typu 1e3 (czyli 100) oraz to że 1 (jeden i spacja) to też poprawny integer, więc ja chciałem takie "inty" traktować wyjątkiem IntegerFormatException. Wszystko ok.

Problem mam z zerami wiodącymi, jeśli ktoś sobie zrobi wyrażenie regularne /[0-9]+/, to oczywiście liczba "000" spełnia warunek. Na razie zaprogramowałem to tak że zamieniając "000" na inta (przy użyciu mojej bilioteki) dostaniemy 0.

Co myślicie, "000" to poprawny int? Czy też powinien rzucić IntegerFormatException?

0

000 to poprawny int. Pytanie czy chcesz to traktować jako zapis ósemkowy czy jako dziesiętny, tzn. czy 008 to poprawny int. To już w całości zależy od Ciebie.

0

W JavaScript literały ósemkowe są już deprecated:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Deprecated_octal

PHP obsługuje literały ósemkowe, z tym że do PHP6 dość dziwnie:
http://php.net/manual/en/language.types.integer.php

0
hauleth napisał(a):

000 to poprawny int. Pytanie czy chcesz to traktować jako zapis ósemkowy czy jako dziesiętny, tzn. czy 008 to poprawny int. To już w całości zależy od Ciebie.

Tylko dziesiętny - ta biblioteka ma być normalna :D (a nie zastawiać pułapki na programistów, o których będą musieć pamiętać).

vpiotr napisał(a):

PHP obsługuje literały ósemkowe, z tym że do PHP6 dość dziwnie:
http://php.net/manual/en/language.types.integer.php

Jestem świadom tego że notacja 010 symbolizuje zapis ósemkowy. Jestem też świadom wszystkich smaczków PHP z 07, 0x13, 10e3, etc. ale między innymi właśnie po to piszę tą bibliotekę, która jak dostanie string to ZAWSZE będzie to zapis dziesiętny składający się tylko ze znaków [0-9] i opcjonalnego minusa. Wszystkie 0x, e, white'spacy, przecinki, kropki, etc. mają być traktowane w tej bibliotece jako "nie int".

Niestety pozostaje mi problem, piszecie wyrażenie regularne /[0-9]+/ i dostajecie "001" - to powinien być poprawny int? Dlatego właśnie ankieta.

0

Ale przecież to nie jest wyrażenie na poprawny int.
Podałem link do strony referencyjnej gdzie masz opisaną regułę (nie do końca jako regexp, ale można sobie przetłumaczyć).

0

Skoro masz system dziesiętny to 000 = 0*10^2 + 0*10^1 + 0*10^0 = 0. Ważniejsze wydaje mi się opisanie kontraktu dla tej Twojej biblioteki.

0
vpiotr napisał(a):

Ale przecież to nie jest wyrażenie na poprawny int.
Podałem link do strony referencyjnej gdzie masz opisaną regułę (nie do końca jako regexp, ale można sobie przetłumaczyć).

Ale ja nie chcę definicji PHP'owej (wszyscy wiemy że PHP ma czasem dziwne pomysły), tylko o to, jaki string - według programisty - powinien/nie powinien być uznany za sensowny int.

yarel napisał(a):

Ważniejsze wydaje mi się opisanie kontraktu dla tej Twojej biblioteki.

No właśnie ja to próbuję z wami ustalić :) Co ma większy sens?

To co już ustaliłem to to, że na 100%:

  • "10" = 10
  • "06" będzie (w mojej bibliotece) = 6 (czyli dziesiętny)
  • "1e3" - wyjątek
  • "1.0" - wyjątek
  • " 1 " - wyjątek
  • etc.
  • "00" - no właśnie, co z tym?
0

Wypadałoby jeszcze odnieść się do traktowania znaków + i - oraz do długości samego stringa opisującego "inta".
Nie wiem jak w PHP, ale taki natywny int często ma określoną dokładność i zakres: MIN..MAX

0
yarel napisał(a):

Wypadałoby jeszcze odnieść się do traktowania znaków + i - oraz do długości samego stringa opisującego "inta".
Nie wiem jak w PHP, ale taki natywny int często ma określoną dokładność i zakres: MIN..MAX

Masz rację. Ja, pisząc bibliotekę uznałem że minus jest akceptowalny przed cyframi, ale plus już nie.

Na maksymalny i minimalny limit ustawiłem 2^32 na 32-bitowych systemach i 2^64 na 64 bitowych. Większe/mniejsze wartości rzucają wyjątek że "zły int".

1

Dla tych wiodących zer, to zastanów się jeszcze nad takim przypadkiem: "0000(zera wypełniające 32/64 bity)1", czy to będzie 1 czy uznasz, że zakres został przekroczony?

0
yarel napisał(a):

Dla tych wiodących zer, to zastanów się jeszcze nad takim przypadkiem: "0000(zera wypełniające 32/64 bity)1", czy to będzie 1 czy uznasz, że zakres został przekroczony?

Good point, ale w mojej implementacji najpierw mam usuwanie tych zer, a dopiero potem tworzenie inta, więc ten problem jakby sam się rozwiązał :)

Ale racja, good point

2

Jeśli w Twojej bibliotece uznajesz 000000001 za 1, to 000000 wypada uznać za 0, inaczej widoczny jest brak konsekwencji. Reguła dla 006 mówi, że wiodące zera są pomijane. Regułą dla 000 to... wyjątek od tejże reguły.
Czyli coś o czym muszę pamiętać. Jak chce to mogę dać wiodące zera i nic się nie stanie CHYBA ŻĘ chcę wartość zera.
Teraz jeśli jej używam i mogę mieć z jakiejś dziwnej przyczyny ileś wiodących zer i zaokrągloną liczbę, to jak mi wyjdzie 006 jest ok. Ale jak sobie ją zaokrąglę do 0 to mam 000 i leci mi wyjątek...

Inny punkt widzenia:
A napisałbyś na kartce:
1 czy 001?
Albo czytając formularz (papierowy) ktoś się spodziewa
Jestem Arek, mam 000000000034 lata?

Skoro biblioteka ma być "normalna" to 0 = 0, 00 = wyjątek. 1 = 1, 01 to wyjątek. Bo nie wiesz czy ktoś: zrobił literówkę i wstawił dwa zamiast jednego, chce być głupio sprytny, hakuje, zapomniał o cyfrze przed zerami. Jeśli jednak ze względu na jakikolwiek powód chcesz na to pozwolić, to zero nie może być traktowane wyjątkowo od innych cyfr.

0

Dziękuję za super odpowiedź @AreQrm !

AreQrm napisał(a):

Jeśli w Twojej bibliotece uznajesz 000000001 za 1, to 000000 wypada uznać za 0, inaczej widoczny jest brak konsekwencji. Reguła dla 006 mówi, że wiodące zera są pomijane. Regułą dla 000 to... wyjątek od tejże reguły.

Zgadzam się

A napisałbyś na kartce:
1 czy 001?
Albo czytając formularz (papierowy) ktoś się spodziewa
Jestem Arek, mam 000000000034 lata?

To chyba nie ma znaczenia, bo jeśli ktoś znajdzie regexpem string 00011, to może zrobić jedną z dwóch rzeczy:

$m->text();       // (string) "00011"
// albo mógłby zrobić
$m->parseInt();   // (int) 11

No właśnie, i co by tu miało sens? Żeby parseInt() rzuciło wyjątek, czy nie? Czy nie mogłoby być tak że jeden int ma kilka reprezentacji w stringach? Jak np 100 oraz 10^2 mają różne notacje, ale odnoszą się do tej samej ilości. Czy kilka aceptowalnych reprezentacji stringa to tworzenie rzeczy o której trzeba pamiętać? Pomocy.

Skoro biblioteka ma być "normalna" to 0 = 0, 00 = wyjątek. 1 = 1, 01 to wyjątek. Bo nie wiesz czy ktoś: zrobił literówkę i wstawił dwa zamiast jednego, chce być głupio sprytny, hakuje, zapomniał o cyfrze przed zerami. Jeśli jednak ze względu na jakikolwiek powód chcesz na to pozwolić, to zero nie może być traktowane wyjątkowo od innych cyfr.

No tak, bardziej bullet-proof byłoby nie pozwalanie na 01, a jedynie na 1.


I masz podobne zdanie co do float'ów? Gdybym chciał zrobić metodę parseFloat(), to miałbym akceptować tylko 0.001, a 00.001 już nie?

0

Tak, tak samo bym rozpatrywał floaty jak inty, w ramach konsekwencji.

Co do samej kwestii zer wiodących i nie dużo zależy od kontekstu użycia i specyfiki języka/środowiska. Ty wiesz najlepiej.
Jednak jeśli chcesz pozwolić na zera, to zastanowiłbym się nad dwiema wersjami i dwiema osobnymi metodami, np:
parseX
parseXWithLeadingZeros

ta druga nazwa wygląda... trochę dziwnie, ale przynajmniej jest opisowa, wiadomo czego się spodziewać.

Inne podejście to jedna metoda i parametr, np config czy options... aczkolwiek osobiście wole osobne metody, bo nie trzeba się zastanawiać co jest domyślną opcją ani grzebać po dokumentacji. Chyba że chcesz mieć kombinacje opcji, ale nie sądzę żeby tak było w tym wypadku.

Oczywiście możesz też mieć osobne klasy (np jakiś wrapper) i zrealizować to też w ten sposób, że użytkownik wybierze metodę z klasy która mu odpowiada:
Parser.ParseX
LeadingZeroParser.ParseX

Oczywiście tylko jeśli masz czas/chęci do tego żeby zrobić dwie osobne wersje. :-)

1
AreQrm napisał(a):

Inne podejście to jedna metoda i parametr, np config czy options... aczkolwiek osobiście wole osobne metody, bo nie trzeba się zastanawiać co jest domyślną opcją ani grzebać po dokumentacji. Chyba że chcesz mieć kombinacje opcji, ale nie sądzę żeby tak było w tym wypadku.

Cały zamysł za biblioteką to jest brak opcjonalnych argumentów, flag, map, etc. Cała decyzja programisty ma się wyświetlać w IDE, więc w grę wchodzą tylko dwie opcje które podałeś: dwie metody lub dwie implementacje.

0

Swietnie, uważam ze to dużo czystsze podejście i bardziej ... ludzkie :-)

Daj znać na co się zdecydowałeś z tymi wiodącymi zerami :)

1
AreQrm napisał(a):

Swietnie, uważam ze to dużo czystsze podejście i bardziej ... ludzkie :-)

Daj znać na co się zdecydowałeś z tymi wiodącymi zerami :)

Myślę że zrobię dwie implementacje

parse()->toInt()
parse()->toFloat()
parse()->ignoreLeadingZeros()->toInt()
parse()->ignoreLeadingZeros()->toFloat() 

0 użytkowników online, w tym zalogowanych: 0, gości: 0