Getallen na de comma weglaten

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Jeroen de wilde

Jeroen de wilde

20/07/2022 16:57:07
Quote Anchor link
Beste,

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.


Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
echo $getal = "18.99"; // Dit zou 18 moeten worden
?>


Alvast bedankt voor de hulp
Gewijzigd op 20/07/2022 17:02:46 door Jeroen de wilde
 
PHP hulp

PHP hulp

19/08/2022 00:24:50
 
Ward van der Put
Moderator

Ward van der Put

20/07/2022 18:20:57
Quote Anchor link
Een geheel getal noemen we een integer of kortweg int in PHP.
Zonder afronding maak je die met de type cast (int):

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$getal
= "18.99";
$integer = (int) $getal;
?>
 
Ad Fundum

Ad Fundum

20/07/2022 20:24:57
Quote Anchor link
Ward zijn antwoord is het meest gangbaar.

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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print explode(".", "18.99")[0]; -- geeft 18 ?>

Het voordeel is dat deze manier werkt zoals je verwacht.
Zelfs met Nederlandse getallen (met komma ipv punt)
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print explode(",", "18,99")[0]; -- geeft 18 ?>

En met grotere getallen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php  print explode(".", "9223372036854775808.99")[0]; -- dit gaat goed  ?>


Als je alleen (int) gebruikt krijg je verkeerde getallen als ze groter worden:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print (int) "9223372036854775808.99"; -- geeft 9223372036854775807 ?>

Of als er letters in staan, houdt (int) daar ook rekening mee, in wetenschappelijke zin:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print (int) "18.99e2"; -- geeft 1899 ?>

Als je een klein getal hebt met een komma er in, dan werkt (float) ook:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print (float) "18,99";  -- geeft 18 ?>

Maar dan weer niet wetenschappelijk:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print (float) "18,99e2"; -- geeft 18 ?>


PHP gebruikt onder water verschillende typen gegevens (scalars), en doet net alsof het verschil niet bestaat:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
<?php
declare(strict_types = 1);
print "18.99e2" + 1;  -- geeft 1900 ?>

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.
Gewijzigd op 20/07/2022 20:45:16 door Ad Fundum
 
- SanThe -

- SanThe -

20/07/2022 21:26:09
Quote Anchor link
Ad Fundum op 20/07/2022 20:24:57:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print (float) "18,99";  -- geeft 18 ?>


Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print (float) "18.99";  -- geeft 18.99 ?>
 
Ivo P

Ivo P

21/07/2022 07:36:28
Quote Anchor link
voor positieve getallen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php echo floor(1234.56);  //  1234 ?>


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.
 
Jan Koehoorn

Jan Koehoorn

22/07/2022 15:39:07
Quote Anchor link
Het maffe is dat je eigenlijk niet met een getal begint, maar met een string waar een getal in zit.

Zo kan het trouwens ook nog:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
$input = '18.99';

var_dump(((int) $input * 100) / 100);
 
Ad Fundum

Ad Fundum

23/07/2022 12:23:31
Quote Anchor link
- SanThe - op 20/07/2022 21:26:09:
Ad Fundum op 20/07/2022 20:24:57:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print (float) "18,99";  // geeft 18 ?>

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print (float) "18.99";  // geeft 18.99 ?>

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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php var_dump(is_float("9223372036854775807" + 1));  // geeft true ?>

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)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$x
= "-18.99";
var_dump(round($x + ($x > 0 ? -.5 : +.5 )));  // geeft -18, of 18 bij 18.99
?>


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.
Gewijzigd op 23/07/2022 13:47:17 door Ad Fundum
 
Ivo P

Ivo P

23/07/2022 16:14:29
Quote Anchor link
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.
 
Ad Fundum

Ad Fundum

23/07/2022 17:43:11
Quote Anchor link
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.
Gewijzigd op 23/07/2022 17:45:14 door Ad Fundum
 
Ivo P

Ivo P

23/07/2022 22:41:54
Quote Anchor link
Er moet wel een zekere mate van verhouding zijn tussen de moeite die iets kost versus de winst die je kunt halen.

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.
 
Jan Koehoorn

Jan Koehoorn

24/07/2022 09:27:18
Quote Anchor link
@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.
 
Ad Fundum

Ad Fundum

24/07/2022 15:45:00
Quote Anchor link
Een eigen cache, wat lief... maar dat is FOUT! :-) (uit: two stupid dogs)

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.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.