1. 程式人生 > 其它 >Python例項——國際標準書號(ISBN)的計算

Python例項——國際標準書號(ISBN)的計算

技術標籤:Python演算法python

Python例項—計算ISBN的校驗和並返回ISBN號

咳咳,科普一下,ISBN的中文名為國際標準書號,簡單來說就是一本書的身份證,經常和條形碼在一起使用。
在這裡插入圖片描述
話不多說,我們直接進入正題:
一、題目要求與分析
  國際標準書號用10為數字唯一標識一本書(哈哈,莫說我騙你噻,自從2007年1月1日起,實行新版ISBN,即在原來的10位數字前加上3點陣圖書產品程式碼“978”,稱為歐洲商品編號,總之就是方便檢索的,這段很尷尬,隱了隱了),最右邊的數字為校驗和,可由其他9位數字計算出來,且d1 + 2d2 + 3d3 + …+ 10d10 必須是11的倍數。校驗和必須是介於0到10中的一個數字,用X標識10。例如:020131452的校驗和是5,因為對於下邊11倍數的公式,5是唯一的介於0到10之間的數:

在這裡插入圖片描述
要求任意給出前9位數字,需要計算校驗和並返回ISBN號。

在這裡插入圖片描述
好吧,不得不說我在構建這個數學公式上耗費了大半元氣。
  題目分析:上邊囉嗦了那麼多,終歸是一個找數字的問題,只是這個數字比較複雜,既滿足在0-10之間,又滿足和其他數相加是11的倍數。如果這個數找到了,那麼什麼輸出ISBN號通通不在話下,我們將問題簡化可以分解成以下三步:
   步驟1: 限定校驗和k(就是那個數,我們也專業點兒)的範圍為0-10
   步驟2: 計算其他數(就是那個 2d2 + 3d3 + …+ 10d10),這裡用number_other表示;
   步驟3: 限定倍數(就是相加是11的倍數那個倍數),這裡用mul表示.

注意:我為什麼要限定倍數nul 呢?
   這個問題是這道題的核心,這裡我不妨談談自己的思路,題中提到11的倍數,但又沒有說這個倍數具體是多少,所以我只能用一個變數mul來代替,讓它從0往後遍歷就好了,但是新的問題出現了;這麼一直遍歷下去也不是辦法,畢竟剎不住車不行呀。
   所以這裡的問題又轉化成了找最大倍數的問題,怎麼找最大倍數呢?不妨看一下這個公式:
在這裡插入圖片描述
這樣就一目瞭然了,對吧!k增大mul增大,所以很容易求出來mul的最大值是45,如果mul超出這個值,則k就不能落在0-10之間了。

講到這裡,想必後邊的程式碼過程大家都勢如破竹了,接下來我們把程式碼給碼列一下……

在這裡插入圖片描述
二、原始碼部分

def ISBN
(n): number = str(n) number_other = 0 j = 2 for i in range(-1,-10,-1): number_other += eval(number[i]) * j j += 1 for mul in range(0,45): #找m可能取到的最大值 for k in range(0,11): if (number_other + k) / 11 == mul: #我滴天,千萬不能用整除 if 0 <= k <=9: d = str(k) if k == 10: d = "x" trueISBN = number + d return (trueISBN) for num in [201314525, 488888913, 977889994, 753231846, 701134069]: trueISBN = ISBN(num) print(trueISBN)

嗯,中規中矩的程式碼,不摻任何浮躁華麗……
三、結構分析
(1) 製造一個函式模組
  害,這種型別的難題不編寫一個函式總覺得對不起自己,一方面是為了養成一個好的習慣,畢竟模組化處理嘛,方便以後幹驚天動地的事,另一方面也看起來舒心,簡潔整齊,有條不紊,多像正規軍。
在這裡插入圖片描述
  注意:函式的引數一定要傳遞正確,要不然浪過頭就不好了。
(2) 計算num_other
  num_other也不是不好算,只是大家有沒有發現那個公式裡數字的計算方式是倒著的,比如020131452(圖也給你了,快看看),所以你要麼倒著讓它每個數進行乘法運算,要麼就是讓他每個數乘以一個倒著增長的數。
在這裡插入圖片描述
我這裡選擇了前者,這裡涉及字串的索引問題,你要是不懂的話可以看看我的“Python字串的索引
於是乎,產生了如下一段程式碼:

 number = str(n)
    number_other = 0
    j = 2
    for i in range(-1,-10,-1): 
           number_other +=  eval(number[i]) * j
           j += 1

  注意:j的值要從2開始,因為乘1被校驗和k(文章一開始提到的那個數)佔了
(3) 計算核心數字k
  通過一開始我們的分析,可以知道要進行兩次限定,於是這裡就用了兩個for迴圈,第一個迴圈限定mul的值最大為45(為啥寫46就不必說了哈,range函式的特性嘛對不對),第二次限定k的範圍為0-10, 所以這個計算核心數字k的過程就悄然躍然紙上:

    for mul in range(0,46):       #找m可能取到的最大值
       for k in range(0,11):
           if (number_other + k) / 11 == mul:        #我滴天,千萬不能用整除
               if 0 <= k <=9:
                   d = str(k)
               if k == 10:
                   d = "x"
               trueISBN = number + d

  注意:
  1 . 因為題中說“用X標識10”,所以記得加一個判斷,判定k是不是10,如果是的話就用X代替;
  2 . 公式描述的那個部分千萬不能用整除,“/”和“//”是有區別的,整除的話在這裡會使很大一部分數都滿足條件,仔細想想?
   3 . 函式的最後要寫return,要不前面寫的都白搭了。切記切記。

四、本次的執行結果
在這裡插入圖片描述
那就在這裡祝你好運咯~


聽說,愛學習的人都特帥……
在這裡插入圖片描述