Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Ongelma PHP plus laskun kanssa

Sivun loppuun

laurii [17.02.2012 00:05:56]

#

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);

?>

tsuriga [17.02.2012 01:00:21]

#

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);

?>

laurii [17.02.2012 08:15:00]

#

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.

Macro [17.02.2012 08:20:36]

#

Ehkä olet määritellyt euron $euro; Silloin €:n korvaaminen ei auta.

Kokeile vaikka funktiota floatval ylimääräisten merkkien parsintaan.

laurii [17.02.2012 08:40:42]

#

Nyt on täysin eurottomassa muodossa, luku ilman tuhat erottimia ja desimaalit on erotettu pisteellä. Silti ongelma on edelleen sama.

qeijo [17.02.2012 09:56:09]

#

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

Lebe80 [17.02.2012 11:00:33]

#

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.

qeijo [17.02.2012 12:03:03]

#

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.

Macro [17.02.2012 14:35:36]

#

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.

<?php
echo "100,95" + "1,05"; // 101
echo "100.95" + "1.05"; // 102
?>

https://www.php.net/manual/en/language.types.float.php

Tukki [17.02.2012 15:10:35]

#

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.

qeijo [17.02.2012 16:33:43]

#

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ä.

tsuriga [17.02.2012 16:44:46]

#

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.

qeijo [17.02.2012 16:49:43]

#

Epäilmeinen tulos johtuu mm. PHP:n dynaamisesta tyypityksestä.

Tukki [17.02.2012 17:52:31]

#

Epäilmeinen tulos johtuu ohjelmointivirheestä joka lienee seurausta siitä että ohjelmoija ei ole ymmärtänyt PHP:n tyypitystä ja tapaa tehdä automaattisia tyyppimuunoksia.

Macro [17.02.2012 22:54:06]

#

Minusta se johtuu pikemminkin suunnitteluvirheestä, jos yritetään laskea yhteen tekstiä. "a" + "b" = 0. Aloittaja taisi kumminkin ymmärtää, että mistä vika johtuu.

tsuriga [17.02.2012 23:29:14]

#

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.

Grez [17.02.2012 23:31:52]

#

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.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta