Getallen na de comma weglaten
Ik ben al een tijdje aan het zoeken maar ik kan de oplossing nergens vinden.
Ik wil mijn getallen na de comma weghalen. Ik heb al de functie round(); getest maar dan komt mijn getal 19 en dit moet 18 blijven.
Alvast bedankt voor de hulp
Gewijzigd op 20/07/2022 17:02:46 door Jeroen de wilde
Zonder afronding maak je die met de type cast (int):
Maar het het hangt er wel van af wat je een 'getal' noemt.
In de vraag gaat het niet om een getal zoals een integer of een float, maar om een byte-reeks.
Als je alleen het hele getal zou willen tonen, kan je ook doen:
Het voordeel is dat deze manier werkt zoals je verwacht.
Zelfs met Nederlandse getallen (met komma ipv punt)
En met grotere getallen:
Als je alleen (int) gebruikt krijg je verkeerde getallen als ze groter worden:
Of als er letters in staan, houdt (int) daar ook rekening mee, in wetenschappelijke zin:
Als je een klein getal hebt met een komma er in, dan werkt (float) ook:
Maar dan weer niet wetenschappelijk:
PHP gebruikt onder water verschillende typen gegevens (scalars), en doet net alsof het verschil niet bestaat:
Dat is omdat PHP weakly typed is, omdat PHP zo bedacht is. In het begin kan je denken dat het wel makkelijk is. Gaandeweg kom je er achter dat PHP (ontzettend) veel nuances kent. Meestal gaat het wel 'gewoon' goed, en soms ook 'gewoon' niet. Dit verschijnsel staat bekend als de Law of Leaky Abstractions.
Ad Fundum op 20/07/2022 20:24:57:
https://php.net/floor
Toevoeging op 21/07/2022 11:01:40:
floor() rondt dus een getal af naar de integer die kleiner is dan de ingevoerde waarde.
1234.56 wordt dus 1234 (of 1234.000, want floor() geeft wel een float terug.
Voor sommigen onverwacht: floor(-1.2) geeft dus -2.000. Want -2 is het gehele getal kleiner dan -1.2. In dit geval proberen we dus niet om dichter bij 0 te komen.
Iets om, afhankelijk van je invoer, rekening mee te houden.
De tegenhanger van floor() is ceil().
Met als zelfde geval dat ceil(-1.2) nu -1.000 oplevert.
Oplossingen met (int) of intval() kan ik me nog in vinden. Al doet intval() ook dingen met "lege array wordt 0"
explode() is wel een rare omweg: je beschouwd het getal dan als een string, laat PHP een array ervan bouwen en dan pak je daar een stukje van.
Dingen die PHP zelf ook, en ook nog eens efficiënter, kan.
Kost je mogelijk enkele milleseconden extra in een test, maar als je dit ergens in een loop moet doen tijdens berekeningen met enkele 1000-en prijzen dan kan zo'n geknutselde oplossing merkbaar trager worden.
- SanThe - op 20/07/2022 21:26:09:
Dat weet jij, dat weet ik.
Het gaat er om dat (float) ook werkt voor het omzetten naar een geheel getal. Tenminste als getallen een komma bevatten, zoals je getallen in het Nederlands schrijft.
Het punt is, dat PHP automatische type casting doet, zonder een warning of notice dat er data verloren gaat. Er wordt een aanname gedaan dat iedereen die impliciete type casting altijd begrijpt. Hoewel correct, was het antwoord van Ward zonder deze uitleg. Dus heb ik wat extra voorbeelden geplaatst van hoe het werkt, voor de bewustwording en tegen negatieve gevolgen van aannames.
Ken je bijvoorbeeld deze al? PHP maakt een float van een string met een integer:
Is dat logisch? Vast, al had ik ook aan kunnen nemen dat PHP er een string van zou maken.
Had ik dat van te voren bedacht toen ik het schreef? Dat niet.
@Ivo: Als je denkt aan afronden met floor() en ceil() naar nul toe, kan je ook dit gebruiken:
Code (php)
De oplossing met explode() zou wat trager kunnen zijn. Het gaat vooral om het inzicht, zodat je de juiste aanpak kan kiezen voor jouw situatie. Getallen als strings is bijvoorbeeld heel gewoon bij grote getallen, de uitbreiding BCMath doet dit ook zo. Of als je een getal in het Nederlands terugkrijgt van een browser, of database, dan krijg je die ook als string.
Performance is geen halszaak bij PHP, meestal gaat het er om dat je snel iets af hebt.
Ad Fundum op 23/07/2022 12:23:31:
Performance is geen halszaak bij PHP, meestal gaat het er om dat je snel iets af hebt.
Ik heb recent een creatieve oplossing voor "ik wil geen query schrijven dus haal ik alle records op en filter met PHP" moeten aanpakken.
Onder omstandigheden had dat een responsetijd van 20 seconden, waar volgens de specs maximaal 1 seconde acceptabel is.
En dat voor een stuk script dat bij 99% van de aanroepen minstens 1x langs komt en waarbij andere kantoorsoftware die landelijk bij 100-en klanten staat daarvan afhankelijk is.
" Performance is geen halszaak bij PHP "
is veel te kort door de bocht.
Ivo P op 23/07/2022 16:14:29:
Ik heb recent een creatieve oplossing voor "ik wil geen query schrijven dus haal ik alle records op en filter met PHP" moeten aanpakken.
Feitelijk onderschrijf je wat ik net zei. Je gaat pas naar performance kijken als het te traag is en niet eerder. Anders had dat script dat je moest aanpakken de productie-omgeving niet eens gehaald. De kans dat de performance merkbaar slechter is met explode() is niet groot. Het hangt af van de omstandigheden. Haal je ineens erg veel data op, of is je server gewoon trager, dan loop je daar eerder tegenaan.
Je hebt zeker gelijk dat er meer over performance te zeggen valt.
een dag onderzoeken of je een of ander statement niet kunt optimaliseren om van 10 naar 9 milliseconden te gaan. Nee dat is de moeite niet.
Maar bestaande functies (floor) zelf opnieuw schrijven?
Dat heeft als eerste nadeel dat het minder optimaal zal werken (mogelijk een minimaal verlies), maar mogelijk ook niet compleet. Is elke uitzonderlijke situatie bedacht?
Daar zou ik toch graag zien dat er dan gekeken wordt of er geen bestaande functie in PHP is die zoiets kan doen.
Het door mij aangehaalde stuk code is geschreven door iemand met minimaal verstand van SQL. (niveau: select * from)
Dat had inderdaad nooit de productie mogen halen, maar helaas is dat wel gebeurd. Gevolg is traagheid. Vooral bij lijsten (tabellen) met enkele honderden tot duizenden records
Maar als "werkt het? " en "klopt de uitkomst" de belangrijkste criteria zijn, dan sluipt zo iets er gewoon in.
En pas optimaliseren als er gepiept wordt.
Dat is een strategie. Maar liever zou ik dat vooral doen. Want als ik kijk hoe complex de code is om alle records op te halen en te combineren met 1 of meerdere andere lijsten en dan die hele berg te doorzoeken.
Het kostte mij ongeveer een uurtje om dat als een query te schrijven die dynamisch uitbreidt met meerdere joins als je "meerdere zoektermen" hebt.
In plaats daarvan is er eerst nog gekozen om een eigen cache op te tuigen die dan eenmaal opgehaalde resultaten in een ander lijstje opslaat in combi met de zoektermen.
Ook leuk.
Maar uiteindelijk minder snel dan de code eerst goed schrijven.
(ja, er zit enige ergenis bij mij over genoemde code-base :-p )
Om de bestaande code te schrijven zou ik zeker een dag nodig gehad hebben.
@Ivo: tegen dit soort problemen loop ik in mijn werk ook aan. Naast wat je al opnoemt neem ik ook altijd mee, of ik verwacht dat er nog nieuwe feature requests gaan komen op de code waar de issue zich voordoet, en of de verwachting is dat het product nog voor langere tijd in productie gebruikt gaat worden. In zo'n geval neig ik eerder naar compleet refactoren en dus schaalbaar maken. In andere gevallen wordt het een compromis, een redelijke oplossing die evengoed werkt.
Als je op dat kleuterniveau moet werken snap ik die ergernis wel. En dan van die vele oplossinkjes, en als de afhankelijkheden groter worden dan moet iemand (lees: jij) dat allemaal weer uit elkaar halen. Terwijl je zo klaar was geweest als je dat in één keer had kunnen doen.
Jij bent niet de enige met die ergernis. Heb ik ook last van. Ongeacht de inschatting vooraf, er wordt toch altijd langer gebruik gemaakt van goede code. Dus kan je het maar meteen beter goed doen, anders kost het achteraf 10x zoveel werk.