歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> 學會在 Linux下防火牆的機制應用

學會在 Linux下防火牆的機制應用

日期:2017/2/27 14:25:11   编辑:更多Linux
  前言    在近日幾個帖子裡面,和QQ群的討論裡面,我發現很多網友都遇到的問題都是因為不恰當地使用了單精度/雙精度數值。因此想專門就這個話題談一下。    單精度和雙精度數值類型最早出現在C語言中(比較通用的語言裡面),在C語言中單精度類型稱為浮點類型(Float),顧名思義是通過浮動小數點來實現數據的存儲。這兩個數據類型最早是為了科學計算而產生的,他能夠給科學計算提供足夠高的精度來存儲對於精度要求比較高的數值。但是與此同時,他也完全符合科學計算中對於數值的觀念:    當我們比較兩個棍子的長度的時候,一種方法是並排放著比較一下,一種方法是分別量出長度。但是事實上世界上並不存在兩根完全一樣長的棍子,我們測量的長度精度受到人類目測能力和測量工具精度的限制。從這個意義上來說,判斷兩根棍子是否一樣長絲毫沒有意義,因為結果一定是False,但是我們可以比較他們兩個哪個更長或者更短。這個例子很好地概括了單精度/雙精度數值類型的設計初衷和存在意義。    基於上述認識,單精度/雙精度數值類型從一開始設計的時候,就不是一個准確的數值類型,他只保證在他這個數值類型的精度之內是准確的,精度之外則不保證,比方說,一個數值5.1,很可能存儲在單精度/雙精度數值中的實際值是5.100000000001或者5.09999999999999。導致這個現象的原因我們可以通過兩種方式來解釋:    簡單的解釋方法:    你可以嘗試在任何一個控件的屬性面板中,設定他的寬度為:3.2CM,當你輸入完畢後,你會發現值自動變成了3.199cm,無論你怎麼改,你都無法輸入3.200CM,因為實際上在電腦中存儲的並不是CM為單位的數值,而是“缇”為單位的數值,而“缇”和CM之間的比值,是個很難被除盡的數,因此你輸入完畢後,電腦自動轉換成了最接近的“缇”值,然後再轉換成厘米顯示到屬性面板上,這一乘一除,兩次四捨五入,誤差就出來了。單精度/雙精度也是類似的原理,其實在二進制存儲的時候,單精度/雙精度都采用了類似相近分數的方法,而這樣的存儲是不可能做到准確的。    深入的解釋方法:    讓我們來看看我們存儲到數字介質中的單精度/雙精度值到底是怎麼樣的,我們使用如下代碼對單精度類型進行一個解剖:    Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)    Public Sub floatTest()  Dim dblVar As Single    dblVar = 5.731 / 8  dblOutput dblVar    dblVar = dblVar * 2  dblOutput dblVar    dblVar = dblVar * 2  dblOutput dblVar    dblVar = dblVar * 2  dblOutput dblVar    dblVar = dblVar * 2  dblOutput dblVar    dblVar = dblVar * 2  dblOutput dblVar    End Sub    Public Sub dblOutput(ByVal dblVar As Single)  Dim bytVar(3) As Byte  Dim i As Integer, j As Integer  Dim strVar As String    CopyMemory ByVal VarPtr(bytVar(0)), ByVal VarPtr(dblVar), 4  strVar = dblVar & ": "  For i = 3 To 0 Step -1  For j = 7 To 0 Step -1  strVar = strVar & (bytVar(i) And 2 ^ j) / 2 ^ j  Next j  strVar = strVar & " "  Next i  Debug.Print strVar    End Sub  運行後我們得到輸出結果(輸出格式為高位左,低位右):    .716375: 00111111 00110111 01100100 01011010  1.43275: 00111111 10110111 01100100 01011010  2.8655: 01000000 00110111 01100100 01011010  5.731: 01000000 10110111 01100100 01011010  11.462: 01000001 00110111 01100100 01011010  22.924: 01000001 10110111 01100100 01011010    這裡,我們把單精度類型轉化成了二進制數據輸出,這裡我們看到,雖然這六個數字完全不同,但是他們的二進制存儲驚人地相似,我們看到紅色標記部分,每次都是加1,事實上,單精度數據類型使用從高位開始第1位作為正負標記位(綠色),第2位到第9位,是一個跨字節的有符號字節類型數據,這個數值決定了小數點移動的方向和位數(紅色),第10位到32位保存一個整數(藍色)在存儲過程中,電腦首先把輸入的值不斷移位(乘除2)直到這個數的整數部分占用了全部24位的整數位,然後把移動的位數寫入浮點部分(紅色),而移位後的結果寫入整數部分(藍色和綠色),小數部分則捨棄。求值的時候則是反向過程,先根據正負位和整數位求值,然後根據紅色部分的整數來進行移位(乘除2的次方),最終才是我們得到的單精度數值。雙精度數值也是同樣原理,只是位數更多而已。    通過解剖單精度數值的二進制存儲格式,我們可以清楚看到,實際上單精度/雙精度的存儲,都要通過乘法和除法,其中必有捨入,如果恰好你的數值在除法中被捨入了,那麼你賦的初值就很可能與你最終存儲的值不完全相同,其中的微小差異,並不與單精度/雙精度的設計目標相違背。    當我們在數據庫中或者VBA代碼中使用一個單精度/雙精度數值的時候,也許你從界面上看不到區別,但是在實際的存儲中,這個差別卻真真切切地就在那裡,當你對其進行相等比較的時候,系統只是簡單地作二進制的比較,界面上無法體現的微小差異,在二進制比較面前卻無處遁形,於是,你的等於比較返回了一個意料之外的False。    結束語    通過本文,我們介紹了單精度/雙精度數據類型的實質以及其特點(優點和缺點),通過比較和解剖我們了解到單精度/雙精度實際上存儲的是一個近似值,浮點的特性決定了他可以存儲非常小的數,也可以存儲極大的數,他的數據精度並不是一個絕對值,而是存儲值的百分比,如果你存儲10的100次方,誤差就可能是10的80次方,如果你存儲10的-100次方,誤差就可能是10的-120次方。因此單精度/雙精度數據類型不能進行相等的比較(或數據庫關聯)。    如果你需要進行等值比較或關聯,那麼有以下幾種方案:    1、使用專為准確度而設計的貨幣類型。    2、使用整數類型存儲,代碼中移位。    3、某些特定情況下可以用文字存儲。




Copyright © Linux教程網 All Rights Reserved