Ipsa Scientia Potestas Est
NNID: ShinNoNoir
Verwijderd
Nee man, dit is de bom:Confusion schreef op dinsdag 16 maart 2010 @ 21:12:
Ik neem aan dat iedereen het eleganter vindt om isInteger te implementeren als:
Java:
1 2 3 public boolean isInteger(String value) { return (value != null) && value.matches("\\d+"); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
| public static void main(String[] args) { Integer integer; if ((integer = tryParseInt("12345")) != null) { int i = integer; System.out.println(i); } } public static Integer tryParseInt(String s) { return tryParseInt(s, 10); } public static Integer tryParseInt(String s, int radix) { if (s == null || radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { return null; } int result = 0; boolean negative = false; int i = 0, max = s.length(); int limit; int multmin; int digit; if (max > 0) { if (s.charAt(0) == '-') { negative = true; limit = Integer.MIN_VALUE; i++; } else { limit = -Integer.MAX_VALUE; } multmin = limit / radix; if (i < max) { digit = Character.digit(s.charAt(i++), radix); if (digit < 0) { return null; } else { result = -digit; } } while (i < max) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(s.charAt(i++), radix); if (digit < 0) { return null; } if (result < multmin) { return null; } result *= radix; if (result < limit + digit) { return null; } result -= digit; } } else { return null; } if (negative) { if (i > 1) { return result; } else { /* Only got "-" */ return null; } } else { return -result; } } |
Gelukkig niet; die vind ik veel te negatief.RayNbow schreef op dinsdag 16 maart 2010 @ 21:17:
En herkent die methode ook negatieve getallen?
Wie trösten wir uns, die Mörder aller Mörder?
http://msdn.microsoft.com/en-us/library/f02979c7.aspx
Death smiles at us all, all a man can do is smile back.
PSN
Java kent geen out parameters/byref.YakuzA schreef op dinsdag 16 maart 2010 @ 23:06:
Bestaat er in Java echt geen Integer.tryParse ??? Deze hele discussie komt een beetje as mierenn***** op mij over
http://msdn.microsoft.com/en-us/library/f02979c7.aspx
Ipsa Scientia Potestas Est
NNID: ShinNoNoir
Voor dit specifieke voorbeeld ligt dat inderdaad misschien op het randje.oisyn schreef op dinsdag 16 maart 2010 @ 20:46:
Als je dit met louter een reguliere expressie wilt afvangen begeef je je echter wel in een gebied waar de aangehaalde opmerking door YopY dan weldegelijk van toepassing is.
In een RL applicatie zal gebruikersinvoer vaak niet rangen over het ganse bereik van de integers. Pakweg iets als leeftijd, jaartallen, aantal huwelijken, etc. Ik ben van mening dat je in dat soort gevallen gewoon rustig een reguliere expressie à la "-?[0-9]{1,9}" kunt gebruiken om je invoer te valideren. Als dat je enige doel is tenminste.
Edit:
Dat klopt, maar dat boeit meestal niet. Als je getallen die je wilt parsen zo groot zijn dat ze tegen de grenzen aanlopen van je integer bereik, dan moet je je eens afvragen of het geen beter idee is, op lange termijn, om voor een long te kiezen. Indien je die gedachtengang aanhoudt dan kun je in meestal "normale" reguliere expressies gebruiken.terje7601 schreef op dinsdag 16 maart 2010 @ 23:52:
Inderdaad, maar dit is niet functioneel equivalent aan het origineel.
[ Voor 18% gewijzigd door Nick The Heazk op 17-03-2010 00:02 ]
Performance is a residue of good design.
Inderdaad, maar dit is niet functioneel equivalent aan het origineel.Confusion schreef op dinsdag 16 maart 2010 @ 21:12:
Ik neem aan dat iedereen het eleganter vindt om isInteger te implementeren als:
Java:
1 2 3 public boolean isInteger(String value) { return (value != null) && value.matches("\\d+"); }
Het probleem met deze hele discussie is m.i. dat het nogal moeilijk is om implementaties te vergelijken als er geen specificaties zijnYakuzA schreef op dinsdag 16 maart 2010 @ 23:06:
Deze hele discussie komt een beetje as mierenn***** op mij over
Specificatie 1 (= het origineel): returns true iff value is a Java int (as defined here)
Implementatie:
m.i. de enige zinnige implementatie:
1
2
3
4
5
6
7
8
| public boolean isInteger(String value) { try { new Integer(value); //of: Integer.parseInt(value); return true; } catch(NFE e) { return false; } } |
Specificatie 2: returns true iff value is an integer (as defined here)
Implementatie:
hier is een regex à la Confusion korter, maar door exact 3 letters toe te voegen aan de implementatie van Specificatie 1 krijg je:
1
2
3
4
5
6
7
8
| public boolean isInteger(String value) { try { new BigInteger(value); return true; } catch(NFE e) { return false; } } |
ik was hier ook eerst voor een regex oneliner gegaan, maar bij nader inzien verkies ik toch dit.
Uit mijn vorige post:Nick The Heazk schreef op dinsdag 16 maart 2010 @ 23:45:
Het punt dat ik wilde maken is dat het wel mogelijk is, terwijl een gebruiker hier al de halve draad lang ervan overtuigd is dat het "onmogelijk" is om dat met reguliere expressies te doen. Die "on-" past voor vele andere woorden, zoals "duidelijk", maar niet voor "mogelijk".
Kom op zeg, je weet best wel wat ik bedoelterje7601 schreef op dinsdag 16 maart 2010 @ 17:56:
EDIT: @Nick hieronder: ja kom, zo ver was ik ook al hoorWaar het mij om gaat is dat zo 'n equivalent veel complexer, (hoogstwaarschijnlijk) trager, niet meer compatibel zodra er iets aan de parseInt specificatie verandert, ... is. Of in 2 woorden: totaal onzinnig.

Nu dat duidelijk is: ik wacht op je implementatie om het tegendeel te bewijzenStatement van terje7601:
De hierboven gegeven implementatie van Specificatie 1 is de enige zinnige implementatie. Het is m.i. onmogelijk om een regex-implementatie te geven die in minstens 1 opzicht (snelheid, leesbaarheid, ...) beter is dan de gegeven implementatie.

Begrijpend lezen?Nick The Heazk schreef op dinsdag 16 maart 2010 @ 23:45:
Edit:
Dat klopt, maar dat boeit meestal niet. [...]


[ Voor 36% gewijzigd door terje7601 op 17-03-2010 00:58 ]
Mega fout, nog altijd. Je gebruikt nooit een dure operatie die exceptions gooit om een simpele voorwaarde te checken. In dit geval is een nieuw Object ala Integer misschien niet zo duur, maar bv in geval van XML parsen weer wel.terje7601 schreef op dinsdag 16 maart 2010 @ 23:52:
m.i. de enige zinnige implementatie:
Java:
1 2 3 4 5 6 7 8 public boolean isInteger(String value) { try { new Integer(value); //of: Integer.parseInt(value); return true; } catch(NFE e) { return false; } }
Tevens suggereert bijna elke isVanEenBepaaldType methode, dat je de input later wilt omzetten naar dat type. Jij zou dus overal dit doen met jouw implementatie van je isInteger methode:
1
2
3
| if(isInteger(someValue)) { Integer integerValue = new Integer(someValue); } |
Je maakt nu dus altijd 2 Integers aan, waarbij je er 1 misbruikt.
Neem je whisky mee, is het te weinig... *zucht*
Tegelijkertijd is het bijna onmogelijk om niet met een behoorlijk complexe constructie XML te valideren... Dus de parser ervoor gebruiken is niet per se een slecht idee dan, ook al is het een hele dure operatie. Je zou kunnen kijken wat de unixtool xmllint intern gebruikt, maar het zou me niks verbazen als ook zij iets gebruiken dat sterk op een parser lijkt, of zelfs gewoon de parserlibrary waar de tool bij meegeleverd is aanspreken.momania schreef op woensdag 17 maart 2010 @ 07:40:
Mega fout, nog altijd. Je gebruikt nooit een dure operatie die exceptions gooit om een simpele voorwaarde te checken. In dit geval is een nieuw Object ala Integer misschien niet zo duur, maar bv in geval van XML parsen weer wel.
Voor zover ik weet is het in ieder geval onmogelijk om XML te valideren met een regexp. Wel zou het met een vereenvoudigde parser kunnen die geen permanente objectboom ervan bouwt.
Ik zou zelf inderdaad verkiezen om proberen de boel om te zetten en er daarbij achter te komen dat het niet lukte, tenzij je vooraf weet dat het vaak niet correct is. Vooral bij het voorbeeld van een ongelimiteerde integer zou ik die gewoon omzetten naar een integer en niet eerst omzetten om te kijken of het kon en dan omzetten om 'm te gebruiken.Tevens suggereert bijna elke isVanEenBepaaldType methode, dat je de input later wilt omzetten naar dat type.
Een (ad-hoc) Regexp er voor inzetten is ook niet bepaald de goedkoopste aanpak (ik gok dat parseInt sneller is), maar dat hangt natuurlijk helemaal van je eisen af. Maar zelf zou ik ook de exception-variant gebruiken, mijn ervaring leert dat userinput bij getallen meestal wel valide is en het dus inderdaad een uitzondering is als dat niet het zo is. Als het vervolgens een gelimiteerde range is, is het parsen en dan controleren met een < en > ook een stuk duidelijker (en eenvoudiger toe te passen, probeer maar eens een bereik tussen 64 en 256 ofzo als regexp te bouwen).
[ Voor 4% gewijzigd door ACM op 17-03-2010 08:21 ]
Daar moet je inderdaad ook goed gaan nadenken over wat user input is en wat machine input is en of al die checks wel echt nodig zijn.ACM schreef op woensdag 17 maart 2010 @ 08:19:
[...]
Tegelijkertijd is het bijna onmogelijk om niet met een behoorlijk complexe constructie XML te valideren...
In de meeste gevallen werk ik met machine input en dan kies ik voor het 'embracing failure' model.
Laat het maar ergens stuk gaan, zolang je er maar klaar voor bent. In geval van machine input is (als alles goed is) 99% toch correcte input en doe je al die checks 99% van de tijd voor niets. Hoezo cpu verspilling.
Mocht het op een JVM echt goed fout gaan, waar hij continu exceptions aan het gooien is, wordt dat zelfs geoptimaliseerd door de JVM en vertraagd er bijna niets
Neem je whisky mee, is het te weinig... *zucht*
1
2
3
4
5
6
7
8
9
10
11
| parseInt("0", 10) returns 0 parseInt("473", 10) returns 473 parseInt("-0", 10) returns 0 parseInt("-FF", 16) returns -255 parseInt("1100110", 2) returns 102 parseInt("2147483647", 10) returns 2147483647 parseInt("-2147483648", 10) returns -2147483648 parseInt("2147483648", 10) throws a NumberFormatException parseInt("99", 8) throws a NumberFormatException parseInt("Kona", 10) throws a NumberFormatException parseInt("Kona", 27) returns 411787 |
Dus je zult altijd moeten matchen op een reeks karakters 0-9, -, a-z / A-Z, en dan zou je ook nog rekening moeten houden met de radix - en dan moet je al gauw een hele reeks if / else of iets in die trant gaan schrijven om alle mogelijke use cases af te gaan. Nee, geef mij maar parseInt en een exception afvangen. Of vang het helemaal niet af, en zeg gewoon dat als een gebruiker verkeerde input invult, hij een dikke exception voor z'n neus krijgt. Het is een unchecked exception, dus je hoeft hem niet af te vangen.
En dat is nog maar voor integers. Doe dit nu ook eens met floats, longs, shorts, bytes, chars, pietjepuks, en wetenschappelijke notatie.
Het enige wat ik stel is, en ik citeer uit mijn vorige post:momania schreef op woensdag 17 maart 2010 @ 07:40:
Mega fout, nog altijd.
Dus ik wacht geduldig op iemand die me een implementatie van Specificatie 1 kan geven, die dit statement weerlegtStatement van terje7601:
De hierboven gegeven implementatie van Specificatie 1 is de enige zinnige implementatie. Het is m.i. onmogelijk om een regex-implementatie te geven die in minstens 1 opzicht (snelheid, leesbaarheid, ...) beter is dan de gegeven implementatie.

Over het algemeen schrijf je controle-functies omdat je een subset van de mogelijke waarden wilt bieden... Dus een controlefunctie opbouwen die alle varianten aan kan is sowieso waarschijnlijk wat overbodig.YopY schreef op woensdag 17 maart 2010 @ 10:14:
Dus je zult altijd moeten matchen op een reeks karakters 0-9, -, a-z / A-Z, en dan zou je ook nog rekening moeten houden met de radix
Dat lijkt me onzin, je valideert voor een bepaalde base, dus daar concentreer je je regex op. Zonder kennis over de basis valt er sowieso niets te valideren. 11111 is een geldige 8 bits int in basis 2, maar niet in basis 10. Voor een reguliere signed 32 bits int in base 10 kom ik opYopY schreef op woensdag 17 maart 2010 @ 10:14:
Ik wil toch wel eens een regex zien die 'alle' NumberFormatExceptions die Integer.parseInt kan veroorzaken voorkomt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| \+?0* ( 1?\d{0,9} | 20\d{8} | 21[0-3]\d{7} | 214[0-6]\d{6} | 2147[0-3]\d{5} | 21474[0-7]\d{4} | 214748[0-2]\d{3} | 2147483[0-5]\d{2} | 21474836[0-5]\d | 214748364[0-7] ) | -0* ( 1?/d{0,9} | 20/d{8} | 21[0-3]\d{7} | 214[0-6]\d{6} | 2147[0-3]\d{5} | 21474[0-7]\d{4} | 214748[0-2]\d{3} | 2147483[0-5]\d{2} | 21474836[0-5]\d | 214748364[0-8] ) |
Er is vast wel een PCRE constructie om die '-' aan het begin te capturen en adhv daarvan een [0-5] danwel [0-6] in de laatste optie te gebruiken zodat al die duplicatie niet nodig is, maar ik had even geen zin om dat op te zoeken.
.edit: woeps dit is voor een 33 bits int, d'Oh
.edit2: zo, nu zou ie wel moeten kloppen.
.edit3: oh duh, die '-' kan natuurlijk ook veel simpeler, de enige special case is -2147483648
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| [-+]?0* ( 1?\d{0,9} | 20\d{8} | 21[0-3]\d{7} | 214[0-6]\d{6} | 2147[0-3]\d{5} | 21474[0-7]\d{4} | 214748[0-2]\d{3} | 2147483[0-5]\d{2} | 21474836[0-5]\d | 214748364[0-7] ) | -0*2147483648 |
[ Voor 28% gewijzigd door .oisyn op 17-03-2010 14:21 ]
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Bovendien, YopY, is [-2^31 ; 2^31 -1] een eindige range. Dat wil zeggen dat door pure enumeratie er altijd een reguliere expressie bestaat voor die taal. Om nog wat olie op het vuur te gooien: je kan ook een reguliere expressie schrijven om alle floats of doubles*, zoals deze in Java gespecifieerd worden, te herkennen
*En nu maar wachten op de eerste vis die hapt.
Neen, uit jou zinnen kan ik niet afleiden dat je begrijpt wat een reguliere expressie is.terje7601 schreef op dinsdag 16 maart 2010 @ 23:52:
Kom op zeg, je weet best wel wat ik bedoelMaar goed, laat ik het even formeel doen. Mijn statement is dus:
Je initiële statement werd weerlegd; je kunt perfect een regex schrijven om alle integers die aan specificatie 1 voldoen te herkennen. Je past je stelling alleen on-the-fly aan.Begrijpend lezen?Omdat ik zit te wachten op een weerlegging van mijn "statement", vermeld ik gewoon even dat zijn implementatie er één is van Specificatie 2, terwijl het origineel er één is van Specificatie 1. Meer zeg ik toch niet?
[ Voor 54% gewijzigd door Nick The Heazk op 17-03-2010 13:04 ]
Performance is a residue of good design.
Oftewel:
1
2
3
| [-+]? (\d+(\.\d*)? | \.\d+) ([eE][-+]?\d+)? |
[ Voor 29% gewijzigd door .oisyn op 17-03-2010 12:49 ]
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Je valt in herhaling...& geloof me, dat kon YopY zelf ook wel bedenken hoor.Nick The Heazk schreef op woensdag 17 maart 2010 @ 12:29:
Bovendien, YopY, is [-2^31 ; 2^31 -1] een eindige range. Dat wil zeggen dat door pure enumeratie er altijd een reguliere expressie bestaat voor die taal.
Voor doubles staat er gewoon een regex in de javadoc, & again: het gaat er helemaal niet om wat al dan niet mogelijk is met regexesNick The Heazk schreef op woensdag 17 maart 2010 @ 12:29:
Om nog wat olie op het vuur te gooien: je kan ook een reguliere expressie schrijven om alle floats of doubles*, zoals deze in Java gespecifieerd worden, te herkennen.

Ik zou het appreciëren als je die arrogante toont achterwege laatNick The Heazk schreef op woensdag 17 maart 2010 @ 12:29:
Maar goed, het heeft weinig zin om hier over door te drammen als je niet weet wat een reguliere expressie is.
*En nu maar wachten op de eerste vis die hapt.
[...]
Neen, uit jou zinnen kan ik niet afleiden dat je begrijpt wat een reguliere expressie is.


Dat doe ik niet, maar goed: ik hoef me niet te verantwoorden. Ik weet waar ik van overtuigd ben, als jij dat per sé verkeerd wil interpreteren: ga je gangNick The Heazk schreef op woensdag 17 maart 2010 @ 12:29:
Je past je stelling alleen on-the-fly aan.

terje7601 schreef op zaterdag 13 maart 2010 @ 16:00:
Dan wil ik je wel eens uitdagen om een methode te schrijven met een regex die precies dit doet (een equivalent van je methode met parseInt dus). Ik weet niet of je de source van die methode (Integer.parseInt) al eens bekeken hebt, maar daar maakt men dus geen gebruik van regexes of patterns of wat dan ook. Bovendien: hoe zul je in je methode verwerken dat het getal tussen Integer.MIN_VALUE & Integer.MAX_VALUE moet liggen zonder de input ook effectief te proberen omzetten naar een int?
De methode die parseInt gebruikt, is de simpelste implementatie mogelijk & garandeert je een correcte implementatie. En bovendien: waarom zou je het wiel opnieuw uitvinden? No offense, maar zolang je geen implementatie kan geven die 1) correct & 2) beduidend sneller is dan de parseInt implementatie, vind ik dit totale onzin hoor.
terje7601 schreef op dinsdag 16 maart 2010 @ 10:50:
Nee, want zoals ik al zei: het is m.i. simpelweg onmogelijk om dit met een regex op te lossen, aangezien je ook moet checken of het in de integer-range ligt.
Maar goed, laat het me zo stellen: ik zal verbaasd zijn als je me ook effectief een regex implementatie kan geven, i.p.v. het gewoon steeds te vermelden
terje7601 schreef op dinsdag 16 maart 2010 @ 17:56:
2) daarop zeg ik dat er m.i. helemaal niets fout aan die code is, & dat het onmogelijk is om een functioneel equivalent van die code te schrijven die gebruik maakt van een regex
Ik denk dat ik zeker niet de enige ben die hieruit de conclusie trekt dat jij niet gelooft dat je een functioneel equivalent bestaat dat enkel gebruik maakt van reguliere expressies. Of al die zinnen zijn erg ongelukkig verwoord, imo, of je probeert jezelf eruit te lullen.Als je het hier niet mee eens bent: geef me een functioneel equivalent van je eigen voorbeeld, met een regex
Waarom vraagt men dan nog naar een implementatie, nadat al tweemaal vermeld werd dat een simpele enumeratie de juiste regex oplevert? Het komt mij over alsof men het maar niet kan geloven dat het mogelijk is. Het is mogelijk want eindig aantal mogelijkheden.terje7601 schreef op woensdag 17 maart 2010 @ 13:39:
Je valt in herhaling...& geloof me, dat kon YopY zelf ook wel bedenken hoor.
Nee, daar heb je gelijk in. Het ging erover dat het erop leek dat jij beweerde dat het onmogelijk is om een reguliere expressie te construeren die alle Java integers herkent. Blij dat we zijn overeengekomen dat het mogelijk is.Voor doubles staat er gewoon een regex in de javadoc, & again: het gaat er helemaal niet om wat al dan niet mogelijk is met regexes
Ik vermoed dat. Ik baseer me daarvoor op de vragen die gesteld worden. Iemand die iets afweet van formele talen weet dat er voor alle eindige talen een reguliere expressie bestaat. Waarom zou je dan vragen naar een implementatie? Bovendien zelfs een heel speciefieke vraag die aantoont waar de regex aan zou moeten voldoen? Eindige talen zijn triviaal, je enumereert ze. Dat lijkt me een vraag die weinig unificeerbaar is met kennis van reguliere expressies (als formele taal).Ik zou het appreciëren als je die arrogante toont achterwege laatHoe kan jij trouwens weten wat iemand al dan niet weet of begrijpt over regexes a.d.h.v. een paar posts?
De andere logische verklaring is dan dat je je ongelukkig hebt uitgedrukt in minstens 5 posts. Maar goed, jij weet wat reguliere talen zijn. Wil je je dan in het vervolg iets genuanceerder uitdrukken wanneer je het bestaan van bepaalde reguliere expressies "onmogelijk" noemt? Dat bespaart een hele discussieDat doe ik niet, maar goed: ik hoef me niet te verantwoorden. Ik weet waar ik van overtuigd ben, als jij dat per sé verkeerd wil interpreteren: ga je gang
Performance is a residue of good design.
Hierin staat een & (AND), dus ik zeg niet dat een implementatie met enkel eigenschap 1 onmogelijk is. Ok goed, als je al die quotes bij elkaar legt, geef ik je graag gelijk: dat kon heel wat beterterje7601 schreef op zaterdag 13 maart 2010 @ 16:00:
zolang je geen implementatie kan geven die 1) correct & 2) beduidend sneller is dan de parseInt implementatie, vind ik dit totale onzin hoor.
YopY zegt (volgens mij) alleen maar: ja, het is mogelijk, maar het zou een gigantisch karwei zijn om voor die methode een equivalente regex te schrijven. Het is dan ook logisch om hiervoor simpelweg parseInt te gebruiken. (m.a.w.: volgens mij bevestigt hij gewoon mijn statementNick The Heazk schreef op woensdag 17 maart 2010 @ 14:08:
Waarom vraagt men dan nog naar een implementatie, nadat al tweemaal vermeld werd dat een simpele enumeratie de juiste regex oplevert? Het komt mij over alsof men het maar niet kan geloven dat het mogelijk is. Het is mogelijk want eindig aantal mogelijkheden.
Amen to thatNick The Heazk schreef op woensdag 17 maart 2010 @ 14:08:
Blij dat we zijn overeengekomen dat het mogelijk is.
Omdat het bestaan van zo 'n regex theorie is, terwijl een implementatie praktijk is. En praktisch gezien is enumeratie vaak geen optie. En inderdaad: de regexes van .oisyn & de javadoc tonen al aan dat voor de hier aangehaalde problemen ook relatief compacte regexes te schrijven zijn (al denk ik dat je met een regex voor de parseInt methode die YopY aanhaalt al gauw een A4'tje kan vullen).Nick The Heazk schreef op woensdag 17 maart 2010 @ 14:08:
Iemand die iets afweet van formele talen weet dat er voor alle eindige talen een reguliere expressie bestaat. Waarom zou je dan vragen naar een implementatie?
DealNick The Heazk schreef op woensdag 17 maart 2010 @ 14:08:
Wil je je dan in het vervolg iets genuanceerder uitdrukken wanneer je het bestaan van bepaalde reguliere expressies "onmogelijk" noemt? Dat bespaart een hele discussie.