Eli tarkoituksena olisi laskea kaksi hintaa yhteen jotta saataisiin kokonaistulos. Mikäli toinen hinnoista muuttuu nelinumeroisiksi, lisää PHP toiseen lukuun nelinumeroisesta luvusta vain ensimmäisen luvun. Onko kukaan kuullut mistä voisi kyseinen virhe johtua?
Kyseessä on Opencart järjestelmä, mutta tämä tuskin vaikuttaa mihinkään mitenkään.
(84,95€+0,00€ = 84,00€) (84,95€+85,95€ = 169,00€) (84,95€+214,05€ = 298,00€) (84,95€+350,00€ = 434,00€) (84,95€+736,95€ = 820,00€) (84,95€+1 230,00€ = 85,00€) (84,95€+5 910,05€ = 89,00€)
<?php $kokonaishinta = $price + $option_value['price']; $kokonaishinta = number_format($kokonaishinta,2); ?>
Serverin locale on sellainen, että PHP parsii merkkijonosta '5 910,05' ainoastaan tuon etuviitosen. En nyt pääse testaamaan *nix-ympäristössä niin en osaa sanoa varmaksi toimiiko tämä, mutta voit kokeilla asettaa localen koodissasi seuraavanlaisesti
<?php // katso serverin tukemat localet komentamalla // serverillä komentokehoitteessa locale -a // kokeillaan kahta suomalaista localea setLocale(LC_ALL, 'fi_FI@euro', 'fi_FI.UTF-8'); // voit tarkistaa lopputuloksen komentamalla var_dump(localeconv()); // jos näkyy euromerkkiä ja thousands separatorina välilyöntiä, eikon kokeilemaan ynnäilyjä ?>
Jos ei lähde tuolla niin konvertoi merkkijonot käsin PHP:n ymmärtämään muotoon. Jos arvot tulevat aina select-elementiltä, voit määritellä optioiden valueiksi nuo PHP:n ymmärtämät muodot. Jätä laskuista myös euromerkit pois. Alla funktiossa oletin, että niitä ei löydy hintoja esittävistä merkkijonoista, esim. $price
:sta, ollenkaan.
<?php function moneyToFloat_fi($val) { return (float)str_replace(array(',', ' '), array('.', ''), $val); } $price1 = moneyToFloat_fi($price1); $price2 = moneyToFloat_fi($price2); echo number_format($price1 + $price2, 2); ?>
Hei, kiitokset vastauksesta. Valitettavasti palvelimeni ei tue tuota ensiksi antamaasi skriptiä. Minulla siis on muuttujissa ja jo euron merkki valmiiksi, sen poistaminen osoittautuikin kinkkisemmäksi kun ainakaan suoraan laittamalla tällä tavalla:
<?php str_replace('€', ' ', $price); ?>
Ei tuo euron merkki kadonnut. Myöskään viimeisen merkin poistaminen luvusta ei toiminut.
Ehkä olet määritellyt euron $euro; Silloin €:n korvaaminen ei auta.
Kokeile vaikka funktiota floatval ylimääräisten merkkien parsintaan.
Nyt on täysin eurottomassa muodossa, luku ilman tuhat erottimia ja desimaalit on erotettu pisteellä. Silti ongelma on edelleen sama.
Epäilmeinen tulos johtuu PHP:n dynaamisesta tyypityksestä. Tarkista onko numerot oikeassa muodossa. Erottimet pisteillä, ilman minkäänlaisia välilyöntejä. Ei tarvitse ajaa liukuluvuiksi jos muoto on lähtökohtaisesti oikea.
Mielestäni on aivan hullua että on edes olemassa funktio millä voidaan "poistaa numerosta ylimääräiset merkit". Sehän on suunnittelu kysymys.
Jotenkin tuntuu virhealttiilta...
qeijo kirjoitti:
Tämä on PHP:n vika.
No... itse en nyt näkisi aikalailla selvien merkkijonojen yhteenlaskua "bugina". Itse tosiaan vääntäisin ensimmäisenä ihan jonkun funktion, joka muuttaisi nuo merkkijonot varmasti luvuiksi, jonka jälkeen käyttäisin pelkästään näitä lukuarvoja laskutoimituksissa, tallennuksissa yms. taustatoiminnoissa ja muuttaisin ne valuutoiksi vain ja ainoastaan käyttäjälle tulostaessa.
Lebe80 kirjoitti:
qeijo kirjoitti:
Tämä on PHP:n vika.
No... itse en nyt näkisi aikalailla selvien merkkijonojen yhteenlaskua "bugina".
Jos PHP ei olisi tyypitön kieli, niin vastaavanlaista ongelmaa ei välttämättä pääsisi niin helposti syntymään.
<?php $luku1 = "50 000"; $luku2 = "9050,20"; $summa = $luku1 + $luku2; // summa on 9100 ?>
Eihän tuollainen pitäisi olla mahdollista, ainakaan ilman huomautusta.
Tuloksesi on tuollainen, koska
a. numeroita käsiteltäessä ne pitää kirjoittaa yhteen ja
b. koska desimaalierotin on piste eikä pilkku.
Yleensäkin ohjelmoinnissa numerot kirjoitetaan yhteen ja pistettä käytetään desimaalierottimena.
qeijo kirjoitti:
Jos PHP ei olisi tyypitön kieli, niin vastaavanlaista ongelmaa ei välttämättä pääsisi niin helposti syntymään.
Vai olisiko kuitenkin niin että mikäli ymmärtää sen että kaikesta huolimatta PHP ei ole tyypitön kieli, niin vastaavanlaista ongelmaa ei välttämättä pääsisi niin helposti syntymään.
Tukki kirjoitti:
Vai olisiko kuitenkin niin että mikäli ymmärtää sen että kaikesta huolimatta PHP ei ole tyypitön kieli, niin vastaavanlaista ongelmaa ei välttämättä pääsisi niin helposti syntymään.
* Tyypitön siinä suhteessa että tyyppi määräytyy automaattisesti. Muuttujaan voidaan asettaa arvo kuin arvo, missä vaiheessa vain. Kaiken lisäksi voi summata väärin formatoituja merkkijonoja yhteen.
Marco kirjoitti:
Tuloksesi on tuollainen, koska
a. numeroita käsiteltäessä ne pitää kirjoittaa yhteen ja... . ..
Ponttini:
Sen sijasta että tulisi virheilmoitus, laskenta suoritetaan ohjelmoijan näkökulmasta väärillä arvoilla. Tyypittömällä (*) kielellä sattuu vain enemmän virheitä.
Ts. PHP on dynaamisesti tyypitetty. Ei voida sanoa sen olevan kielen vika, jos ohjelmoija ei tunne sen ominaisuuksia. Parempi ilmaisu olisi sanoa epäilmeisten tulosten johtuvan PHP:n dynaamisesta tyypityksestä, koska toiminta on ominaista sille, ei kielelle.
Epäilmeinen tulos johtuu mm. PHP:n dynaamisesta tyypityksestä.
Epäilmeinen tulos johtuu ohjelmointivirheestä joka lienee seurausta siitä että ohjelmoija ei ole ymmärtänyt PHP:n tyypitystä ja tapaa tehdä automaattisia tyyppimuunoksia.
Minusta se johtuu pikemminkin suunnitteluvirheestä, jos yritetään laskea yhteen tekstiä. "a" + "b" = 0. Aloittaja taisi kumminkin ymmärtää, että mistä vika johtuu.
Dynaaminen tyypitys tarkoittaa sitä, että castaus, jonka ohjelmoija "normaalisti" tekisi itse, hoidetaan kielen puolesta automaagisesti. Eli vaikka koodissa näyttääkin siltä, että lasketaan yhteen merkkijonoja, käytännössä merkkijonot muutetaan ensin tulkin tai kääntäjän arvaamaan tyyppiin. Dynaamisten kielien kontekstissa näihin konversiohin luottaminen on täysin normaalia, sehän on koko dynaamisen tyypityksen kantava idea. Mutta kuten moneen kertaan jo todettua, on riskialtista luottaa automaattikonversiohin ellei todellakin tiedä, mitä tekee.
Macro kirjoitti:
Minusta se johtuu pikemminkin suunnitteluvirheestä, jos yritetään laskea yhteen tekstiä. "a" + "b" = 0.
Minusta "a"+"b" pitäisi antaa virhe tai ainakin varoitus. "7"+"8.66" sen sijaan pitäisi toimia ihan kivasti. Käsittääkseni aloittaja ei kuitenkaan yrittänyt laskea yhteen tekstejä vaan numeroita, jotka tosin hänen epäonnekseen oli huonossa muodossa.
Aihe on jo aika vanha, joten et voi enää vastata siihen.