Posts

Showing posts from October, 2021

[計算機概論] float-point

先找一篇別人寫好的,這樣就不用從頭到尾都自己寫筆記(欸): 從 IEEE 754 標準來看為什麼浮點誤差是無法避免的 (以下代稱為「該文」) 看過 于天立教授的計算機概論單元 2 之後,我對該文的補充筆記: 「超127 格式」是怎麼回事 exponent 的部分,採用的是 Excess 的定義方式(可參考 定義負數 ),所以,要把十進位的數字 n ,轉成定義中對應的 bits 時,要先把 n 加上某個微調的值,然後轉成二進位,才會得到定義中對應的 bits。如何取得微調的值?看 exponent 有幾個 bits,例如說是 k bits,那麼那個微調的值,就是 2 k-1 -1。該文中的單精度浮點數,exponent 是 8 bits,所以微調的值是 2 8-1 -1 = 127。 不過,真的完全按照 定義負數 中的說法的話,那個微調的值應該是 2 k-1 才對。我目前的判斷是,這個 -1 的誤差,可能是來自於兩者的「哪組 bits 對應到哪個數字」的定義表,有一點點出入,但規律是沒有變的。 fraction 為什麼要去掉 1 正規化後,數字的格式(先不考慮 0 這個數字)固定會長成 n * 2 m 這個樣子,其中 1 ≤ n < 2。既然正規化後,所有數字都一定是 1.XXX * 2 m 這個長相,那麼整數部分的 1 乾脆就不要存起來,這樣省下來的記憶體空間,還可以拿來做更有效的運用。那麼,要怎麼表示 0 呢?所有 bits 都是 0 的話,就代表是 0。如果把「全部都是 0 的 bits」,依照 sign、exponent 跟 fraction 的規則是解讀的話,以單精度浮點數為例,我猜,得到的數字是 2 -128 (或者是 -126 次方?因為 IEEE-754 Floating Point Converter 在 exponent 都是零的時候,顯示的是 -126 次方),總之就會是這個正規化所能代表的最小的正數。但因為要把這個全部是 0 的 bits 改成拿來表示 0,所以「這個正規化所能代表的最小的正數」就被犧牲,變成無法被表示了。 其他 知道浮點數的表示方式後,就可以計算出這個表示方法中,「比 0 大的數字中最小的那個數字(我猜,應該是:sign 是 0,exponent 全部是 0,fraction 只有最後一

[計算機概論] overflow

以二補數這個定義負數的方式為例,若長度只有 3 bits 的話,能表示的整數數字範圍只有 -4 ~ 3,對照表如下: bits 代表的十進位正負數 011 3 010 2 001 1 000 0 111 -1 110 -2 101 -3 100 -4 overflow 會發生在「數字超出 -4 ~ 3 此範圍」的時候。在之前「 定義負數 」這篇文章中,介紹過,二補數這個定義負數的方式,加法依然可以使用原本二進位的加法。但如果加起來的值超出 -4 ~ 3,例如 2 + 3 根據定義即為 010 + 011 = 101,101 根據定義,代表的數字是 -3。「2 + 3 = -3」這個結果,就是 overflow 又或者, -3 + (-4),根據定義即為 101 + 100 = 1001,因為只有 3 bit 的空間,所以只剩下最後三個 bits 001 ,根據定義, 001 代表的數字是 1。產生「-3 + (-4) = 1」的現象 我之前寫 picoCTF 的 General Skills 題目時,有一題是 flag shop,看了 別人的解答 也不太明白發生了什麼事。今天終於知道了! 參考資料 台大開放式課程 于天立教授的計算機概論單元 2

shop_platform - 部署到 GCP (2)

Image
監聽 80 port(後來發現其實不需要) 試著在 80 port 上開啟伺服器,但是失敗了 flora@*******:~/shop_platform$ pipenv run gunicorn "app:create_app()" Loading .env environment variables... [2021-10-28 13:38:45 +0000] [22652] [INFO] Starting gunicorn 20.1.0 [2021-10-28 13:38:45 +0000] [22652] [ERROR] Retrying in 1 second. [2021-10-28 13:38:46 +0000] [22652] [ERROR] Retrying in 1 second. [2021-10-28 13:38:47 +0000] [22652] [ERROR] Retrying in 1 second. [2021-10-28 13:38:48 +0000] [22652] [ERROR] Retrying in 1 second. [2021-10-28 13:38:49 +0000] [22652] [ERROR] Retrying in 1 second. [2021-10-28 13:38:50 +0000] [22652] [ERROR] Can't connect to ('0.0.0.0', 80) 換成別的 port 就沒問題 flora@*******:~/shop_platform$ pipenv run gunicorn --bind 0.0.0.0:5000 "app:create_app()" Loading .env environment variables... [2021-10-28 14:00:11 +0000] [22879] [INFO] Starting gunicorn 20.1.0 [2021-10-28 14:00:11 +0000] [22879] [INFO] Listening at: http://0.0.0.0:5000 (22879) [2021-10-28 14:00:11 +0000] [22879] [

shop_platform - 部署到 GCP (1)

我不太確定,終端機裡的哪些訊息要打馬賽克,姑且憑感覺自己手動打馬賽克******* 過程 啟用 Google Cloud 服務、建立專案、安裝 Google Cloud SDK 按照 WordPress / 架站教學一:使用 Google 台灣主機免費架設自己的網站 (Mac/Win版) 的教學,啟用 Google Cloud 服務、建立專案、安裝 Google Cloud SDK 話說,啟用 Google Cloud 服務時,教學裡有提到「雖然這裡一定要提供信用卡資訊,不過 Google 也說明了這只是在驗證你不是機器人。在你升級為付費帳號之前,即使你用完了一年 300 美金的免費額度,Google 也不會自動收取任何費用。」但我的 visa 卡在我啟用 Google Cloud 服務時被扣了台幣 40 元。不太確定是什麼情況。 安裝 Google Cloud SDK 過程如下: (base) [~/Downloads/google-cloud-sdk] $ ./install.sh Welcome to the Google Cloud SDK! To help improve the quality of this product, we collect anonymized usage data and anonymized stacktraces when crashes are encountered; additional information is available at <https://cloud.google.com/sdk/usage-statistics>. This data is handled in accordance with our privacy policy <https://cloud.google.com/terms/cloud-privacy-notice>. You may choose to opt in this collection now (by choosing 'Y' at the below prompt), or at any time in the future by running the following command:

[計算機概論] 定義負數

第一種定義方式:Two’s Complement Notation 補數:所謂補數(Complement)是指兩個數字加起來等於某數時,則稱該二數互為某數的補數;例如3的10補數為7,同理7的10補數為3(來源: 數字系統及數字系統的轉換 ) 以長度為三個位元為例:定義方式如下 bits 代表的十進位正負數 代表的十進位正整數(這一欄只是輔助對照用的,重點不在這一欄) 011 3 3 010 2 2 001 1 1 000 0 0 111 -1 7 110 -2 6 101 -3 5 100 -4 4 轉換方式 以十進位的 -3 轉為 bits 為例:3 寫成二進位是 01 1 ,從右邊往左邊,在遇到第一個 1 之前(含第一個 1)都 照抄 ,第一個 1 之後的都 反著抄 ,所以得到 10 1 。 以十進位的 -2 轉為 bits 為例:2 寫成二進位是 0 10 ,從右邊往左邊,在遇到第一個 1 之前(含第一個 1)都 照抄 ,第一個 1 之後的都 反著抄 ,所以得到 1 10 。 另一種轉換方式:長度限制為 3 位元, 2 3 = 8(十進位)。-3 轉為 bits:8 - 3 = 5,十進位的 5 轉成二進位 101,剛好就是 -3 的 bits 優點 不用另外製作減法電路,用原本的二進位加法電路就夠用了 例如 3 - 1 即為 3 + (-1),相當於 011 + 111 = 1010,因為長度只有三位元,所以最開頭的 1 記不住,只剩下後三位 010,010 轉成十進位是 2。所以 3 - 1 = 2 要判斷正負數,只要看最左邊的 bit 是 0 或是 1 就可以知道了。1 開頭的是負數 缺點 排序的電路要重寫。原本 100(轉成十進位正整數的話是 4) > 000(轉成十進位正整數的

[計算機概論] SR Flip-Flop

Image
SR Flip-Flop 又稱為 SR Latch 定義(根據于天立教授計算機概論單元 1) 有兩個 input,分別稱為 set(簡稱 S) 和 reset(簡稱 R) output 計算方式 兩個 input 都是 0:output 維持之前的狀態(這個真是挺有趣的,會導致同樣的 input 有不同的 output。以前在哲學所念形式邏輯時,從來沒遇過這種設定) 兩個 input 都是 1:output undefined S 負責把 output 設成 1 R 負責把 output 設成 0 用途:儲存一個 bit 的值 實作方式至少有兩種(圖片來自于天立教授計算機概論單元 1 的 投影片 ): 參考資料 台大開放式課程 于天立教授的計算機概論 Sequential Logic Circuits :不知道是我有所誤會,還是有不同的定義習慣,這篇文章裡,是設定「兩個 input 都是 0:output undefined」、「兩個 input 都是 1:output 維持之前的狀態」,跟于天立教授講的剛好相反 CS-計概04:閘與電路 :這裡的設定也是「兩個 input 都是 0:output undefined」、「兩個 input 都是 1:output 維持之前的狀態」

[計算機概論] ASCII 表怎麼讀

Image
圖片來自 英文維基百科 ,箭頭和圈圈是我加上去的 以表上的 A 為例,代表他的編碼是 (16 * 4) + 1 = 65 參考資料 台大開放式課程,于天立教授的計算機概論單元 1

shop_platform - 上傳圖片

Image
賣家上架商品時,可以展示商品圖片。表單原本只能填寫圖片網址。 現在要改成可以直接上傳圖片。 form 表單可以上傳圖片 前端 form 標籤屬性加上 enctype="multipart/form-data" 若沒有加的話,enctype 預設使用 application/x-www-form-urlencoded,這樣的話: 後端只收得到檔案名稱: request.form.get('field_name') 是檔案名稱 收不到檔案內容: request.files.get('field_name') 是 None input 標籤,改成 type="file" ,前端防呆加上 accept=".jpg,.jpge,.png,.gif" 後端 驗證檔案副檔名 驗證檔案大小 將圖片存在伺服器 後端收到的檔案,資料型態是 werkzeug.datastructures.FileStorage ,可以用 save 方法,把檔案存到指定檔案,目前是存在 static/product_images/ 資料夾。 為了避免不同使用者,不約而同上傳同樣名稱的檔案,我用 uuid 作為新的檔案名稱,再加上副檔名。 前端會用 /static/product_images/<string:filename> 這個網址請求圖片資源。 目前圖片的網址,透露了後端是用什麼資料夾結構儲存圖片資源。但路由和真正的檔案位置其實是可以分開的,設定好路由,在路由中帶入檔名,然後用 flask.send_from_directory 就可以指定從哪個資料夾取出檔案,這樣一來,網址就不會暴露檔案位置了。 commit: feat: user can upload product picture 將圖片存在 imgur 伺服器目前部署在 heroku 上。因為 heroku 的免費方案,有 the maximum slug size is 500 MB 的限制,所以要把圖片都存在伺服器有困難。因此想改成存在 imgur 上。 imgur api 官網 推薦

shop_platform - 部署到 Heroku 後,session 有問題

問題描述 部署到 heroku 後,出現一些奇怪的現象: 輸入正確登入資訊,按下登入按鈕後: 有時候會登入成功,跳轉到首頁,但切換幾個畫面後,又變成沒有登入的狀態 跳轉到首頁,但仍是未登入狀態,也沒有出現任何 flash 訊息。切換幾個畫面後,出現遲來的 flash 訊息 仍是跳轉到登入頁面,沒有出現任何 flash 訊息 在未登入狀態下,將物品加入購物車(此時購物車內容會存在 session)。點選購物車頁面後: 有時候會跳轉到首頁,也沒有出現任何 flash 訊息。切換幾個畫面後,出現遲來的 flash 訊息 成功顯示購物車中的商品,但若繼續點選購物車頁面,過沒多久就提示「購物車中沒有商品」 上述操作(導覽列判斷使用者是否已登入、flash、未登入時的購物車),多半是跟 session 有關係,讓我有一種「cookie 或 session 好像會突然出現,又突然消失」的感覺。 另外,如果在本地也跟 heroku 一樣使用 gunicorn "app:create_app()" 指令開啟伺服器,一切功能都正常,無法重現 heroku 上的問題。 查資料 Flask sessions not persisting on heroku - stackoverflow Application Server、WSGI Server、Web Server 之間的關係 nginx+gunicorn/uwsgi+python web 的前世今生 Flask想上線? 你還需要一些酷東西 Heroku gunicorn flask login is not working properly - stackoverflow gunicorn 19 with WebSocket on Heroku These applications based on the Flask-SocketIO extension are stateful. If multiple workers ar

ModernWeb 2021 與會隨筆(10/12~10/15)

Modern Web 2021 共筆 10/13 依照古法、純手工打造的視訊聊天網站,不純免錢!/ GitHub 範例程式碼 確認是否有在線上:long polling or websocket(比較建議用後者) 取得麥克風和鏡頭權限: MediaDevices.getUserMedia() 用 WebRTC 傳送串流資料:socket.io Signal Server:peer.js。Signal Sever 的作用類似媒人婆,介紹雙方的資訊(Session Description Protocol,SDP,紀錄 IP、agent、decode、encode 等資訊),雙方認識後就讓他們點對點直接溝通,不必再透過媒人婆溝通 如果是內網 IP,會透過 NAT(Network Address Translation)轉成 public IP STUN(Simple Traversal of UDP over NATs)、處理不同網路的連線(via TURN server):不知道這兩個是啥,暫且搜尋到這篇介紹: 明辨STUN/TURN協定 輕鬆跨越NAT建立連線 10/14:測試 八個沒人告訴你的網頁自動化測試挑戰/ 林佳妤(Melo) 主要針對 code less 的工具而言(用螢幕錄製的方式製作 test case),例如 Selenium IDE 測試「滑鼠滑過元件後要發生指定變化」,錄製時會錄到非目標的「mouse over」事件。解一:選擇目標 mouse over。解二:調整敏感度 按鈕被別的東西擋住,使用者按不到,但測試按得到,造成測試通過,但其實功能不合格。解:verify visibility 如何確認按鈕已經 disable? 有 HTML 和 CSS 兩種方法可以 disable 按鈕,檢查是否有使用其中一種方法 HTML:disable 屬性 CSS: 解一:用 get computed style 計算 pointer-events 屬性(需要比較多程式背景知識)。解二:verify css(code-less)

shop_platform - sqlalchemy.exc.TimeoutError

發生的問題 啟動伺服器後,第二十一次請求「需要查詢資料庫」的頁面時,會出現「sqlalchemy.exc.TimeoutError: QueuePool limit of size 10 overflow 10 reached, connection timed out, timeout 30.00 (Background on this error at: https://sqlalche.me/e/14/3o7r )」的錯誤訊息。如果請求是不需要查詢資料庫的(例如靜態檔案或前往登入頁面),就不會發生此錯誤。 把 size 和 overflow 設定成更小的數字,可以更快重現這個錯誤 。 感覺起來,就像查詢完資料庫以後,沒有把 connection 釋出一樣,導致「size + overflow」是多少,就只能查詢多少次資料庫。 發現瀏覽器每向伺服器請求一次「需要查詢資料庫」的頁面,在 MySQL Workbench 用 show PROCESSLIST; 指令的查詢結果就會多出一筆資料,筆數達到 size + overflow 時,若再次請求「需要查詢資料庫」的頁面,就會噴 QueuePool limit of size 10 overflow 10 reached 的錯誤。關閉伺服器時,那幾筆資料才會被刪除。 嘗試過但失敗的方法 app.run(debug=False) 自己註冊一個關閉 session 的函式 @app.teardown_appcontext # 改成 @app.teardown_request 也沒用 def teardown_db(exception): db.session.remove() # 改成 db.session.close() 也沒用 print('***** session.remove') # 這一行有印出來,所以此函式有被執行 把 FLASK_ENV=development 拿掉 ,於是 FLASK_ENV 變成預設的 production app.config["SQLALCHEMY_COMMIT_ON_TEARDOWN"] = True 終於成功的方法 第一種方法:用 Ap