Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Lukujen/merkkijonojen käsittely

Sivun loppuun

dartvaneri [13.03.2012 21:54:33]

#

Excelissä minulla on seuraavanlainen kaava:

7*MID(10000000000+1000000*$K$4+$K$7;2;1)

Tarkoitus olisi saada sama kaava verkkosivuille, siis vain tuon laskun tulos.
En tarka tiedä mitä noi MID ja ; tarkoittavat, mutta kokeilin excelillä vähän miten se käyttäytyy eli, kun

esim.
K4 = 557
K7 = 176
7*MID(10557000176;2;1)

Nyt tuo MID functio ottaa tuolta luvun, joka on kohdassa 2, eli 0 ja kertoo sen seitsemällä. Miten toteutta tämä php:llä, okeiastaan, jos sais tiedon, että miten saan hajotettua tuon luvun taulukkoon, niin pärjäisin, kun voisin hake ko. luvun taulukon indexi arvolla [1].

Grez [13.03.2012 22:02:31]

#

Olis kyllä kiva tietää kuka ton kököstyksen on tehnyt ja mikä sen tarkoitus on.

PHP:llä voi tehdä saman seuraavasti

$K4 = 557;
$K7 = 176;
$tulos = 7*substr(10000000000+1000000*$K4+$K7, 1, 1);

dartvaneri [13.03.2012 22:05:47]

#

Okei, kiitos! Se on viitenumeron viimeisen numeron lasku kaavasta otettu pätkä :)

Tällainen siitä nyt tuli, en tiedä onko hölömösti toteutettu, mutta ainakin toimii.

	$ViiteAlku = (10000000*$LaskunNro)+(10*$AsiakkaanNro);
	$A1 = 7*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 1, 1);
	$A2 = 1*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 2, 1);
	$A3 = 3*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 3, 1);
	$A4 = 7*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 4, 1);
	$A5 = 1*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 5, 1);
	$A6 = 3*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 6, 1);
	$A7 = 7*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 7, 1);
	$A8 = 1*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 8, 1);
	$A9 = 3*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 9, 1);
	$A10 = 7*substr(10000000000+1000000*$LaskunNro+$AsiakkaanNro, 10, 1);
	$A = 10-substr($A1+$A2+$A3+$A4+$A5+$A6+$A7+$A8+$A9+$A10,2,1);
	$ViiteNro = $ViiteAlku + $A;

?>

vehkis91 [13.03.2012 23:05:54]

#

Tee silmukalla toi, niin ei tarvii noin paljoo toistoa...

Grez [14.03.2012 00:33:10]

#

HGHH..

Joo, viitenumeron laskemiseen voi toki käyttää jotain järkevääkin algoritmia. Eli vaikka joku kadotettu sielu on joutunut purkkaamaan sen Exceliin, niin ei se tarkoita, että se olisi pakko tehdä esim. PHP:ssä samalla tavalla. Toi siksi toisekseen laskee tietyissä tilanteissa viitteen väärin tai antaa virheilmoituksen.

Ehdotan:

$ViiteAlku = $LaskunNro . str_pad($AsiakkaanNro, 6, '0', STR_PAD_LEFT);
$tarkiste = 1000; //10 jaollinen luku yli 657
$L = strlen($ViiteAlku);
$kertoimet = array(1,7,3);
for ($i = 0; $i < $L; $i++) { $tarkiste -= ($ViiteAlku[$i] * $kertoimet[($L-$i)%3]); }
$Viite = $ViiteAlku . ($tarkiste % 10);

Lebe80 [14.03.2012 10:13:03]

#

Pyh, itse ajattelin käyttää mieluummin tuota dartvanerin tapaa, tuleepahan koodi samalla obfuskoitua!

Grez [14.03.2012 10:28:01]

#

Lebe80 kirjoitti:

Pyh, itse ajattelin käyttää mieluummin tuota dartvanerin tapaa, tuleepahan koodi samalla obfuskoitua!

Joo ja sitten voi myöhemmin laskuttaa myös bugikorjauksista. Tai ehkä ketään ei haittaa että joka 10. viitenumero on virheellinen ja lisäksi tietyt asiakas- ja laskunumerot kaataa softan. :D

Plus että huono obfuskaatio -> ei aiheuta epäselvyyttä siitä mitä yritetään tehdä, ainoastaan siitä miksi on tehty.

dartvaneri [14.03.2012 12:38:23]

#

Joo ja toi 10 viitenumeron välein tuleva virhe näyttänee johtuvan siitä, että tuossa excelin kaavassa olikin ennen tuohon $ViiteAlku muuttujaan lisäämistä sellainen funktio, joka ottaa ensimmäisen numeron oikealta vasemmalle luettuna, ja lisää sen tuohon $ViiteAlkuun.

Grez kirjoitti:

ja lisäksi tietyt asiakas- ja laskunumerot kaataa softan

Kuinka?

Edit. Ja osaatko sanoa mistä johtuen, kun menee luvut todella suuriksi tulee tällaista:

5.6069589613554E+20

Kun sun koodilla tulee tällaista:

56069589595895176589589584

Grez [14.03.2012 13:00:30]

#

dartvaneri kirjoitti:

Kuinka?

Jaa, ajattelin että se olisi kaatunut, jos laskutus ja asiakasnumerot on lyhyehköjä, eli vaikka 3 numeroa pitkiä ja sisältää keskimäärin 5:ttä pienempiä numeroita. Eli tällöin yritettäisiin ottaa luvusta, joka on pienempi kuin 100 kolmas numero.

Mutta koska PHP ei valita moisesta, niin se ei näköjään kaadu, ainoastaan laskee väärin. PHP ei valita siitä, että yritetään ottaa merkki merkkijonon ulkopuolelta vaan palauttaa vaan tyhjän merkkijonon. Jotkut muut kielet antaa tuosta virheilmoituksen ja koska vain silmämääräisesti katsoin koodiasi, niin sekoitin tuollaiseen muuhun kieleen.

Eli se siis vain laskee väärin niissä tilanteissa, joissa A1+$A2+$A3+$A4+$A5+$A6+$A7+$A8+$A9+$A10 on alle sata.

dartvaneri kirjoitti:

Ja osaatko sanoa mistä johtuen, kun menee luvut todella suuriksi tulee tällaista

Johtuu siitä, että sun koodi laskee niitä turhaan numeroina kun mun koodi käsittelee sitä tekstinä.

Tuossa voi vielä vertailla tuloksia: http://grez.info/putka/dartvaneri/dv-viite.php

dartvaneri [14.03.2012 13:42:28]

#

Okei, mietinpä vain, että kuinka 10000000000+1000000*$LaskunNro+$AsiakkaanNro tämän laskun tuloksena voi olla alta 100 vaikka $LaskunNro olisi 112 ja $AsiakkaanNro olisi 221? Jos nyt edes tuota tarkoitit, sillä siitä tulee ihan kuten sunkin koodilla, 1130002210.
Onko toi sitten väärin laskettu?

Grez [14.03.2012 14:16:29]

#

Tarkoitin ihan sitä mitä kirjoitinkin, eli että kun "$A1+$A2+$A3+$A4+$A5+$A6+$A7+$A8+$A9+$A10 on alle sata"

Tuolla esimerkilläsi 112 ja 221 se on 33.

dartvaneri kirjoitti:

vaikka $LaskunNro olisi 112 ja $AsiakkaanNro olisi 221? Jos nyt edes tuota tarkoitit, sillä siitä tulee ihan kuten sunkin koodilla, 1130002210.

Mun koodilla tulee 1120002217 ja sun koodilla 1120002220. Toki en tiedä, jos olet tehnyt koodiin muutoksia sen jälkeen kun postasit sen tähän ketjuun.

Tuolla voit edelleen käydä vertailemassa:
http://grez.info/putka/dartvaneri/dv-viite.php (lähdekoodi)

Ja kyllä, 1130002210 on ihan oikea viite, jos syötteet on 113 ja 221, mutta sun koodilla kylläkin tulee 1130002220

dartvaneri [14.03.2012 14:30:51]

#

Aivan. Joo kyllä mää siihen yhden if-lauseen lisäsin, jonka ansiosta se toimii kuten koodisi, paitsi isoilla luvuilla.

Grez [14.03.2012 14:48:39]

#

Täytyy kyllä sanoa, että en keksi mitä hyötyä siinä olisi if lauseesta enkä itse asiassa sitäkään miten pelkällä if-lauseella sen saisi toimimaan.

Tuo pitkistä numeroista murehtiminenkin on jokseenkin turhaa, kun tuo versiosi ei kuitenkaan toimi oikein yli 4 numeroa pitkille laskunumeroille.

dartvaneri [14.03.2012 15:05:20]

#

Joo siis kyllä tuo sinun versiosi on toimivampi ja lyhyem... etc.

Itseasiassa, kun enemmälti kokeilin, ei se aina anna samaa tulosta, mutta joissain kohissa antaa, eli oikeastaan sama toteutus, kuin siinä alkuperäisessä kaavassa:

if($A.lengt != 1){
	$A = substr($A,1,1);
}

Purkkaa...Purkkaa

Grez [14.03.2012 15:17:38]

#

Tuollakaan se ei toimi jos toi $A1..$A10 summa on alle 10.

Ja tulos on virheellinen jos tarkistenumeroksi tulee 0.

Vähemmän purkka vaihtoehto olisi:

$A = substr(900-($A1+$A2+$A3+$A4+$A5+$A6+$A7+$A8+$A9+$A10),2,1);

Ja vielä vähemmän purkka vaihtoehto:

$A = (900-($A1+$A2+$A3+$A4+$A5+$A6+$A7+$A8+$A9+$A10))%10;

Kummallakin vaihtoehdolla tuo jopa toimisi, kun laskunumero on max 4 merkkiä ja asiakasnumero max 6 merkkiä.

jtha [27.03.2012 11:15:38]

#

Toimiiko tämä?

Private Function TeeTarkaste731(ByVal NumeroTeksti as String)
  Kerroin = 7
  For I = Len(NumeroTeksti) To 1 Step -1
    summa = summa + Kerroin * Val(Mid(NumeroTeksti, I, 1))
    Kerroin = Kerroin \ 2
    If Kerroin < 1 Then Kerroin = 7
  Next
  While (summa + Tarkastenumero) Mod 10 <> 0
    Tarkastenumero = Tarkastenumero + 1
  Wend
  TeeTarkaste731 = Tarkastenumero
End Function

Grez [27.03.2012 12:00:35]

#

Näyttäisi toimivan, mutta en ihan ymmärrä tuota while loopin tarvetta.

Private Function TeeTarkaste731(ByVal NumeroTeksti as String)
  Kerroin = 7
  For I = Len(NumeroTeksti) To 1 Step -1
    summa = summa + Kerroin * Val(Mid(NumeroTeksti, I, 1))
    Kerroin = Kerroin \ 2
    If Kerroin < 1 Then Kerroin = 7
  Next
  Teetarkaste731 = (1000-Summa) Mod 10
End Function

(Mielestäni vakiintunut kirjoitusmuoto on tarkiste, ei tarkaste)

jtha [27.03.2012 17:34:23]

#

Tuo tuli tehtyä noin kun jossakin määrittelyissä sanottiin (muistaakseni), että lukua kasvatetaan lähimpään kymmeneen ja lukujen erotus on tarkaste.

Minulle aukeaa hieman huonommin tuo 1000:sta vähentäminen, toimiiko kaikilla luvuilla vastaavasti - no ei ehkä ihan lyhyillä tarvitsekaan.

(Juu, se on "tarkiste". Olin hetken 'tarkistajana' ja katsoin netistä :-))

Grez [27.03.2012 17:59:51]

#

Suurin mahdollinen viitteen painotettujen numeroiden summa on 657 (7*7*9 + 6*3*9 + 6*1*9), joten 1000:sta vähentäminen ja jakojäännös toimii millä tahansa luvulla. Jakojäännöksen luonteesta johtuen 1000 paikalla käy mikä tahansa muukin 660 tai suurempi 10 jaollinen luku. 1000 nyt vaan oli kivan pyöreä ja nopea kirjoittaa sen enempää miettimättä.

Jos ei halua yhtään miettiä niin seuraava on tietysti vielä varmempi, eli toimisi vaikka 500 merkkiä pitkällä viitteellä (tosin viitteen max. pituus on 19 merkkiä + tarkiste):

Teetarkaste731 = (10-(Summa Mod 10)) Mod 10

jtha [27.03.2012 18:19:38]

#

Aivan, tuo vaikuttaa fiksulta.
(Pyrin kyllä välttämään turhia luuppeja, mutta kun nuo sormet ovat aivojani nopeammat..)


Sivun alkuun

Vastaus

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

Tietoa sivustosta