Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: Pankkiviivakoodin tarkisteen laskeminen

Sivun loppuun

multigamerr85 [09.11.2015 21:22:51]

#

Mites tuo pankkiviivakoodin (Code128 C) tarkiste tehdään, eli sen laskemiseenhan käytetään Modulo 103-algoritmia.

Eli jos viivakoodin sisältö on:

[105]579440520200360820048831509000000868516259619897100612[74][stop]

niin tuo 74 on se tarkiste ja tuo stop on loppumerkki.

Tämän oppaan ohjeet siihen ovat:

Pankkiviivakoodi-opas.pdf kirjoitti:

Tarkiste lasketaan Modulo 103 -algoritmin mukaisesti symbolin
kaikkien merkkien (siis myös alkumerkin)
perusteella lukuun ottamatta loppumerkkiä seuraavasti:
1. Alkumerkki saa arvon 105.
2. Symbolin jokaiselle merkille (arvoparille) annetaan painoarvo.
Alkumerkki saa painon 1. Sen jälkeen ensimmäinen arvopari saa painon 1, toinen
painon 2, kolmas painon 3 jne. aina painoarvoon 27 asti.
Huom! Sekä alkumerkki että ensimmäinen arvopari saavat painoarvon 1.
3. Jokainen arvopari kerrotaan painollaan ja näin saadut tulot lasketaan yhteen.
4. Yhteissumma jaetaan luvulla 103.
5. Kohdan 3 jakolaskun jakojäännös on tarkisteen arvo.

Miten tämä toteutetaan pythonilla?

Metabolix [09.11.2015 23:23:12]

#

Code128-viivakoodin Code C:

def Code128_C(data):
	s = str(data)
	for i in s:
		if i not in "0123456789":
			raise ValueError("Code128_C can only contain numeric data!")
	if len(s) % 2 != 0:
		raise ValueError("Code128_C needs an even number of digits.")
	t = [int(s[i:i+2]) for i in range(0, len(s), 2)]
	x = 105 + sum(t[i] * (i+1) for i in range(len(t)))
	return [105] + t + [x % 103, 106]

Käyttöesimerkki:

s = "579440520200360820048831509000000868516259619897100612"
t = Code128_C(s)

print(t)
# [105, 57, 94, 40, 52, 2, 0, 36, 8, 20, 4, 88, 31, 50, 90, 0, 0, 8, 68, 51, 62, 59, 61, 98, 97, 10, 6, 12, 74, 106]

print(" ".join("%02d" % i for i in t))
# 105 57 94 40 52 02 00 36 08 20 04 88 31 50 90 00 00 08 68 51 62 59 61 98 97 10 06 12 74 106

multigamerr85 [10.11.2015 08:08:28]

#

Kiitos Metabolix.

Chiman [10.11.2015 10:14:23]

#

Merkkijonon koostumisen pelkästään numeroista voi tarkistaa myös näin:

if not s.isnumeric():
	raise ValueError("Code128_C can only contain numeric data!")

Grez [10.11.2015 10:35:15]

#

Chiman kirjoitti:

(10.11.2015 10:14:23): Merkkijonon koostumisen pelkästään nume­rois­ta...

Eipäs tässä tapauksessa. Esimerkiksi ⅕ ei kelpaa CODE128_C koodiin.

Itse asiassa tuo Pythonin isnumeric tuntuu äkkiseltään turhakkeelta kun "32⅕45" on numeerinen mutta vaikkapa "3,141" tai "3.141" ei.

Chiman [10.11.2015 11:33:44]

#

Grez kirjoitti:

Eipäs tässä tapauksessa. Esimerkiksi ⅕ ei kelpaa CODE128_C koodiin.

Näinpä onkin. isnumericin docstring ei vihjaissut tuosta mitään. Pythonin varsinaisessa dokumentaatiossa tuo kerrotaan.

Sitten tekisin näin:

if any(c not in "0123456789" for c in s):
	raise ValueError("Code128_C can only contain numeric data!")

multigamerr85 [10.11.2015 20:03:30]

#

Grez kirjoitti:

Sitten tekisin näin:

if any(c not in "0123456789" for c in s):
	raise ValueError("Code128_C can only contain numeric data!")

Eli laitanko koodin tähän muotoon:

def Code128_C(data):
    s = str(data)
    if any(c not in "0123456789" for c in s):
        raise ValueError("Code128_C can only contain numeric data!")

    if len(s) % 2 != 0:
        raise ValueError("Code128_C needs an even number of digits.")
    t = [int(s[i:i+2]) for i in range(0, len(s), 2)]
    x = 105 + sum(t[i] * (i+1) for i in range(len(t)))
    return [105] + t + [x % 103, 106]

s = "579440520200360820048831509000000868516259619897100612"
t = Code128_C(s)

print(t)
# [105, 57, 94, 40, 52, 2, 0, 36, 8, 20, 4, 88, 31, 50, 90, 0, 0, 8, 68, 51, 62, 59, 61, 98, 97, 10, 6, 12, 74, 106]

print(" ".join("%02d" % i for i in t))
# 105 57 94 40 52 02 00 36 08 20 04 88 31 50 90 00 00 08 68 51 62 59 61 98 97 10 06 12 74 106

Metabolix [10.11.2015 21:21:06]

#

Kyllä, voit muuttaa koodia noin, jos haluat. Chimanin neuvo ei sinänsä toiminnallisesti paranna koodia, vaan kyseessä on lähinnä tyyliseikka. (Itse käytän Pythonia niin vähän, että en aina keksi tuollaisia mahdollisuuksia.)

multigamerr85 [10.11.2015 21:58:32]

#

Selvä, pääasiahan on se, että ohjelmakoodi toimii kuten pitää.

Chiman [11.11.2015 14:09:11]

#

Metabolix kirjoitti:

Chimanin neuvo ei sinänsä toiminnallisesti paranna koodia, vaan kyseessä on lähinnä tyyliseikka. (Itse käytän Pythonia niin vähän, että en aina keksi tuollaisia mahdollisuuksia.)

Koodisi oli muuten niin osuva, että tuo mainittu kohta houkutti parantamiseen. Ironisesti tilalle ensin tarjoamani koodi olikin toiminnallisesti huonompi. Hyvä että Grez korjasi.

Muuten, isnumericin sijasta merkkijonon isdigit-metodi hoitanee homman oikein. Tuon poikkeustekstin numeric-sana altisti näköjään ajatusvirheelle.

>>> [x for x in ('', 'a', '4a', '½', '-2', '7.0', '5', '007', '1e4', '0x21') if x.isdigit()]
['5', '007']

Lisäys: myös '½' mukaan testiin.


Sivun alkuun

Vastaus

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

Tietoa sivustosta