在電腦中，定點數是指用固定整數位數表達分數的格式，屬於實數資料型別中一種。例如美元常會表示到二位小數，以分來表示，即為一種定點數。有時定點數也會要求要有固定的整數位數。定點數與更復雜的浮點數相對。 在定點數表示法中，小數部份和整數部份一樣，也會表示為進位制底數 b 的冪次，不過是以負數冪次來表示。最常見的定點數表示法是十進位制（底數為 10）和二進位制（底數為 2）。若儲存了 n 位的小數，其數值一定是 bn 的整數倍。定點數表示法也會用來省略整數中較低位數的值，例如將金錢表示為 1000 美元的整數倍。 在人們處理有小數的十進位制數字時，會在整數和小數之間加上小數點（ 或是 ）。不過定點數中，整數和小數的位數長度是依程式的規畫來決定。 在機械計算器中主要會使用定點數運算。由於大多數現代的中央處理器就有浮點運算器（FPU），只有在特殊的應用中才使用定點數運算，例如低價的嵌入式系統微處理器以及微控制器，這類的應用強調高需求速度，低電力需求及小積體電路區域，例如影像、或數字訊號處理，或是一些這種表示法比較適合問題本質的議題。後者的例子是會計學的金錢單位，非整數的金額也需要進行四捨五入，另一種情形是在產生函式的查詢表。 表示法 定點數表示法 小數數值 用整數表示的值 000 0 05 50 099 99 2 200 141 1410 314160 31416 定點數型別的值其實就是個整數，需要額外做比例進位，進多少位需要根據具體的定點數型別決定。例如 123 使用 11000 縮放係數的定點數表示時是 1230；1230000 使用 1000 縮放係數的定點數表示也是 1230。與浮點數不同，相同型別的定點數中所有值的縮放係數都是一致的，在計算過程中也保持不變。此表示法可以用標準的整數算術邏輯單元來進行有理數的計算。 二進制定點數下的負數常常會用二補數型式下的有號整數表示，其中隱含著縮放係數（或小數長度）。數值的正負號會依最高位元而定（1 表示負值，0 表示正值）。就是小數位數等於或大於整個數字的位置也是如此。例如，8 位元二進位制有號整數 11110101 2 11，若分別配合 3 5 及 12 的隱含小數長度，數值為1123 88、1125 034375、和11212 0002685546875。 另一種作法，負號可以用「符號 大小」的有符號數處理表示法以整數來表示，另外表示正負號，也有隱含的縮放係數。此作法常用於十進位制的定點數貞算中。例如有號的十進位制五位數 00025 10，配合 3 5 and 12 的隱含十進位制小數長度，數值為25103 25000、25105 000025 和251012 0000000000025。 程式一般會假設所有儲存在變數中的定點數，或是指令集架構產生的定點數，都會有相同的縮放係數。程式設計者可以依需要的測量精度以及實際數值的範圍來選擇縮放係數。 變數或是公式的縮放係數不一定會直接在程式碼中出現。好皊軟體工程實務會要求在軟體文件中說明縮放係數，至少也要在原始碼的註釋中說明。 定點數的最大值，可以透過將其內部所使用的整數的最大值乘以縮放係數求得，最小值同理。 縮放係數的選擇 為了效率考量，縮放係數（scaling factor）一般會是基數 b（2 或是 10）的正冪次，或是負冪次，因此實際內部仍然可以用類似整數的方式處理。不過縮放係數也需依應用而定。因此許多的數字可能其數值其實是用二進位制記錄，但為了使用方便人類讀寫，縮放係數仍選擇 10 的冪，10 的冪的縮放係數也可以配合國際單位制，因為選擇特定的縮放係數，可能相當於使用另外一個大小較適合的單位，例如使用釐米或微米，而不是使用米。 不過有時也會使用其它縮放係數，例如可以用 13600 縮放係數的定點數來表示以小時為單位的時間值，可以精確到秒。 就算針對定點數進行最仔細的四捨五入，縮放係數 S 的定點數，其誤差最大會到其整數數 05，因此誤差的實際數值範圍是 05 S。若縮放係數越小，所得到結果越準確。 不過，縮放係數越小也表示相同長度下所能記錄的數值會比較小。定點數下可以儲存的最大數值會對應可儲存的最大整數，再乘以轉換係數，其最小值也類似。例如，下表列出在 16 位元有號二進制定點數下，不同小數位元 f 下的縮放係數 S，可以表示的最大值和最小值 Vmin 和 Vmax，以及其精度 δ S2。 16 位元有號二進制定點數的引數 f S δ Vmin Vmax 3 123 8 4 0262144 0262143 0 120 1 05 0032768 0032767 5 125 132 0016 102400000 102396875 14 1214 116384 0000031 200000000000000 199993896484375 15 1215 132768 0000016 1000000000000000 0999969482421875 16 1216 165536 0000008 05000000000000000 04999847412109375 20 1220 11048576 00000005 003125000000000000000 003124904632568359375 精確值 在二進位制的定點數中，考慮二進位制下的分數 a2m（例如 116 或 1732），若其縮放係數為 12n，且 n m，即可以精確的用二進制定點數表示。不過大部份的十進位制小數（如 01 或 0123）在二進位制下會是無窮迴圈小數，因此無法用二進製表示其精確值。 十進位制的情形也類似，考慮十進位制下的分數 a10m（例如 1100 或 371000）若其縮放係數為 110n，且 n m，即可以精確的用十進制定點數表示。若分母是二的次冪的分數 a2m（如 18 0125 或 1732 053125），且 n m，也可以精確的用十進制定點數表示。 若考慮有理數 ab，其中 a 和 b 互質，b 為正數。若用二進位制的定點數表示，只有在 b 是 2 的次冪下才能表示其精確值，若用十進位制的定點數表示，只有在 b 的質因數沒有 2 和 5 以外的數字時，才能表示其精確值。 Q 格式 表示字長和二進位制定點數中小數點位置的方法有很多種。下面的例子中，使用 f 表示小數部分位數、m 表示整數部分位數、s 表示符號位位數、b 表示總位數，其中「位數」均為位元位。 Qf：稱作「Q 格式」，Q15 表示 15 個小數位。這樣的記法存在歧義，因為沒有包含字長，但實際使用時一般可以根據目標處理器平臺判斷字長為 16 或者 32 位。 Qmf：無歧義的 Q 格式，因為整個字是補碼整數，所以符號位長度可以根據其它資訊推導而來。例如 Q130 表示該數有 1 個整數位、30 個小數位，是 32 位補碼整數。 fxmb：「fx 格式」與上述 Q 格式類似，區別在於點號後是字長。例如 fx116 表示有 1 個整數位、15 個小數位的 16 位字。 smf：PS2 中所使用的表示法，包含符號位資訊。PS2 GS Users Guide Chapter 71 Explanatory Notes080 表示 8 位無符號整數。 和浮點數的比較 定點數的運算比浮點數要快，需要的硬體也比較少。假如要計算的數值範圍事先就已知道，而且限制在較小的範圍內，定點數運算可以有效的使用其位元。例如，用 32 位元表示從 0 到 1 的數字，定點數下的誤差會小於 12 1010，而浮點數的誤差則為 596 1010，因為其中有九個位元表示指數以及指數的正負號，因此誤差較大。 使用定點數運算的程式，不會受到是否有浮點運算器（FPU）的影響，可移植性比浮點數要高。在 IEEE 754 普及之前，相同資料在浮點運算後的結果會依處理器廠商而不同，因此此一優點影響很大。 許多早期的嵌入型系統沒有浮點運算器，整數運算單元需要的邏輯閘和積體電路較少，而且低速備下，用軟體模擬浮點運算的速度太慢，無法實用。早期個人電腦和電子遊戲機的處理器（例如 Intel 80386 和 Intel 80486）都沒有浮點運算器。 定點格式下的絕對解析度（二個連續數值之間的差），在整個數值範圍下都是定值，例如是縮放係數 S。相反的定點格式下的相對解析度，在整個數值範圍下都是定值，但其絕對解析度會隨數值而變化，變化甚至會到數個數量值。 在許多應用中，定點運算的四捨五入以及捨去誤差比較好分析。不過在定點運算下，程式設計者需要花較多的心力，例如為了避免溢位，需要確認計算中所有中間值的範圍，為了要調整到理想的縮放係數，需要有額外的程式處理訊號轉換。 應用 十進制定點數常用在儲存貨幣價值上，因為浮點數的複雜捨入原則，往往會造成負擔。例如開源的現金管理應用程式，GnuCash，以 C 語言撰寫，就因為此原因從 16 版起由浮點數改為定點數。 自從 1960 年代末期，一直到 1980 年代，二進制定點數常用在要用到大量數學實時計算的程式，例如飛行模擬器以及核電廠控制演演算法。在許多數字訊號處理應用或是客製的微處理器中仍常使用定點數。像有關角度的計算，就會使用（BAM）。 在 STM32G4 系列的 CORDIC 協同處理器，以及 JPEG 影像壓縮使用的離散餘弦變換（DCT）演演算法，都使用二進制定點數。 運算 加法和減法 若要針對二個縮放係數相同的數字相加或相減，直接針對數字運算即可，運算結果也會有相同的縮放係數，因此可以儲存在變數中，或是用在後續的運算中。只要運算過程沒有算術溢位（也就是運算過程和結果都可以正確的儲存），其結果就會是精確的。若二個縮放係數不相同的數字要相加減，需轉換到相同的縮放係數，才能相加減。 乘法 若要將二個定點數相乘，可以直接將其數字相乘，再假設最後積的縮放係數是被乘數和乘數縮放係數的乘積即可。只要沒有捨入，也沒有運算溢位，結果會是精確的。 例如，要將 123（縮放係數 11000，實際數值是 0123）和 25（縮放係數 110，實際數值是 25）會得到 12325 3075，縮放係數是 11000110 110000，因此實際數值是 03075。另一個例子是將第一個數字和 155（縮放係數 132，實際數值是 15532 484375）相乘，所得的數字是 123155 19065，其縮放係數是 11000132 132000，因此實際數值是 1906532000 059578125。 為了避免溢位，儲存乘積的變數長度會比被乘數和乘數的要長，例如被乘數和乘數分別是十進位制的二位數，乘積需要用十進位制的四位數來儲存，才不會溢位。 除法 若要將二個定點數相除，可以直接將其數字相除，再假設最後商的縮放係數是被除數和除數縮放係數相除後的商即可。一般來說，相除時會出現捨入，因此結果無法完全精確。 例如，3456（縮放係數 1100，實際數值 3456）和 1234（縮放係數 11000，實際數值 1234）相除會得到 34561234 3（有捨入），其縮放係數為 110011000 10，因此實際數值是 30。若第一個數除以 155（縮放係數 132，實際數值 15532 484375），會得到 3456155 22（有捨入），其縮放係數為 1100132 32100 825，因此數值為 2232100 704。 在結果不精確時，若被除數使用較小的縮放係數，可以縮小（甚至消除）因為捨入產生的誤差。例如，r 123，表示為定點數 123，縮放係數 1100，而 s 625，表示為 6250，縮放係數 11000，相除後的結果是 1236250 0（有捨入），其縮放係數為 110011000 10。若 r 先轉換為縮放係數 11000000 的數字，定點數表示會是 11000000，其結果會是 1230000625 197（有捨入），其縮放係數為 11000（實際數值是 0197）。其精確值是 123625 01968，後者的計算結果比較接近。 縮放係數的調整 在定點數運算中，常常需要調整定點數的縮放係數，以下是一些可能的原因 將一數值存到不同縮放係數的變數中。 將二個數值轉換為相同的縮放係數，以便相加減或是比較。 一個數值在和其他數值相乘或是相除後，恢復成原來的縮放係數。 要增加除法運算的精度 要確保乘積或是商的縮放係數是像 10n 或 2n，基數的次冪。 要確保運算結果可以在沒有溢位的情形下儲存在變數內。 為了要減少處理定點數硬體的成本。 若要將縮放係數 R 的定點數轉換為縮放係數 S 的定點數，整數需要乘以 RS。以 123（ 123100）為例，若要從縮放係數 R1100，轉換為縮放係數 S11000，整數 123 要乘以 110011000 10，因此即為 12301000。 若二個縮放係數都是基數的次冪，調整縮放係數只是除去較低位數的數字，或是在較低位數增加零。不過，此一運算不能改變符號位元，因此需要像算術移位運算一樣的方式，延伸其符號位元。 若 R 不能被 S 整除（特別是新的縮放係數 S 比原來的縮放係數 R 要大），產生的整數需要進行數值修約。 若 r 和 s 是定點數，其縮放係數分別為 R 和 S，運算 r rs 需要將整數相乘，再除以 S，所得結果可能會有數值修約，也有可能會溢位。 例如，二個定點數的縮放係數都是 1100，將 123 乘以 025，其整數相乘是 123 乘以 25，得到 3075，而縮放係數是 110000，為了還原到 1100 的縮放係數，3075 需乘以 1100，也就是除以 100，依數值修約方法的不同，所得結果可能是 31（031）或是 30（030）。 而運算 r rs 需要將整數相除，再乘以 S，所得結果可能會有數值修約，也有可能會溢位。 和浮點數的轉換 若要將浮點數轉換為定點數，可以將浮點數除以縮放係數 S，再修約到最接近的整數。需確認對應的變數有足夠的大小儲存所得的結果。依縮放係數、變數長度，以及數值大小的不同，轉換有可能需要修約。 若要將定點數轉換為浮點數，可以將定點數乘以縮放係數 S。若整數的絕對值超過 224（IEEE 單精度浮點數）或 253（IEEE 雙精度浮點數），可能會需要修約。若 S 非常大或是非常小，可能會有溢位或算術下溢（小於可以表示的最小數）的情形。 硬體支援 比例和正規化 一般的處理器沒有特別支援定點數的運算，不過大部份二進位運算的處理器會有快速的位操作指令，因此可以在很短的時間進行和二的乘冪的乘法或除法，有些還有算術移位指令，在和二的乘冪相乘除的同時，還可以保留數字的正負號。 早期像是或是 Burroughs B3500 的電腦會使用二進碼十進數（BCD）表示法來處理整數，在十進位制下每一個位數會分別用四個次元來儲存，有些處理器還使用此一運算方式，因此可以用移位的方式來處理和十的乘冪相乘除的運算。 有些 DSP 架構會支援特定的定點運算格式，例如有號的 n 位元數字，其中有 n1 位是儲存小數（其儲存數值範圍從 1 到幾乎是 1 的），其中會有特別包括正規化的乘法指令，在相乘後將小數位數從 2n2 位調整回 n1 位。若 DSP 沒有支援此一機能，程式設計者需要用夠大的暫存器或是暫存變數來儲存此數值，再另外用程式進行正規化處理。 溢位 若運算結果的數值太大，超過要儲存位置可以儲存的範圍，就會出現溢位。若是加法或是減法，所得結果會比運算數字多一個位元，若是乘法，所得結果的位元數會是二個運算數字位元數的和。 若出現溢位，最高位元的資訊可能會因此而更改，若儲存空間有 n 位元，所儲存的會是除以 2n 的餘數，而最高位元會視為符號位元，因此結果的大小及正負號都可能改變。 有些處理器有，或是在溢位時進行的異常處理。有些處理器則會有飽和運算，若相加或是相減的結果可能會溢位，考慮其正負號，儲存相同符號，絕對值最大的數值。， 飽和運算只保留了正負號，無法保留結果的大小，在實務上可能不太實用。一般比較簡單及安全的作法是選擇適當的縮放係數以及變數儲存長度，避免溢位的可能性，或者在運算之前先檢查運算結果是否可能溢位。 程式語言支援 有些程式語言明確支援定點數表示法及運算，著名的有 PLI、COBOL、Ada、JOVIAL 及。這些程式語言中提供定點數的數值資料型別，可能是二進位制或十進位制，可以指定給變數或是函式。編譯器會在處理有關的程式碼時自動進行轉換，例如處理類似 r s t u 的程式碼，讀寫這些變數的值，或是將這些資料型別轉換為浮點數時。 這類的程式語言多半是在 1940 年至 1990 年之間設計的，現今的程式語言多半都不提供定點數資料型別，也不提供相關的係數轉換。有些較古老，但仍很受歡迎的程式語言也是如此，例如 Fortran、C 語言和 C。浮點處理器的普及，以及嚴格標準化的行為，大幅的減少二進制定點數的需求。有些程式語言支援（例如 C和 Python），也去除了大多數需要十進位制固點數的需求。很少數需要固點數的情形，會由程式設計師寫程式實現，並且有明確的係數轉換，這在任何程式語言都可以實現。 另一方面，所有關聯式資料庫以及 SQL 表示法都支援用十進制定點數來進行數值的儲存以及運算。PostgreSQL 有一種特別的 numeric 型態，可以精確的儲存數值，位數最多可以到 1000 位 PostgreSQL manual section 812 Arbitrary Precision Numbers 。 ISO 在 2008 年針對 C 語言提出了有關定點數資料型態的擴充提案，目的為了方便程式在嵌入式處理器上執行 JTC1SC22WG14 2008 status of TR 18037 Embedded C 。GCC 的編譯器也支援定點數。 具體範例 十進制定點數乘法 以下是二個三位小數的定點數乘法。 105001050 110500 005010500 10500052500011025000 因為有三位小數，因此保留小數最後的 0。為了要重整為整數乘法，先將數字都乘以 1000，使數字都變成整數，之後再乘以 11000 二次，使最終結果不會改變，其算式如下 10500103 1050103 103103 105001050 106 11 025 000 106 11025000 若用其他的進位制（例如方便計算的二進位制），也可以用類似的原理來進行，因為二進位制的左移或右移都相當是數值的乘 2 或是除 2。十進位制的三位數接近二進位制的十位數，因此可以將 05 表示為有十位小數的二進位制數字。最低的近似值是 00000110011 10 822321 120 05 21 005 00000110011（二進位制） 乘法會變成 10101002310000110011210 213 101010010000110011 213 10110000010111100 213 10110000010111100 若轉為十進位制，保留三位小數，會是 11023。 二進制定點數運算 考慮計算 12 乘 56 的乘積，使用有 16 位小數的二進制定點數。為了要表示這二個數字，需先將二個數字乘以 216，所得的是 786432 和 3670016，再四捨五入到最近整數，是 78643 和 367002，此數字可以放在 32 位元的 word 中，用二補數的有號數表示法。 二個數字相乘會得到 35 位元的整數 28862138286，小數位數則有 32 位。若放在 32 位元的整數中，會出現溢位，而且會失去最高位的位元，因此，應該存在有號的 64 位元整數變數或是暫存器中。 若結果要儲存在也是 16 位小數的資料格式中，上述的整數需要除以 216，結果會是 44040128，再四捨五入到最近整數，可以用先加上 215，再將數字右移 16 位元的方式達到相同效果，其結果是 440401，表示的數值是 67199859619140625。考慮此格式的精度，結果可以表示為 6719986 0000008（不考慮運算近似產生的誤差）。正確結果是 12 56 672。 標示方式 為了要精確的說明定點數的引數，有許多不同的標示方式。在以下的表中，f 表示小數位元數，m 表示整數位元數，s 表示符號位元，而 b 是總位元數。 COBOL 程式語言一開始支援任意大小以及小數位數的十進制定點數，其格式會用 PIC 命令功能（directive）來標示。例如 PIC S9999V99 代表六位數整數，二位小數的的十進位制有號數。 PLI 程式語言使用 REAL FIXED BINARY pf 的 construct 來標示，標示二進制定點數，其中共有 p 位數（不考慮符號），其中小數是 f 位數，總共的有號整數有 p1 位數，其轉換係數是 12f。也可以用 COMPLEX 代替 REAL，用 DECIMAL 代替 BINARY 來表示十進位制。 在 Ada 程式語言中，數值型態的表示法會像 type F is delta 001 range 1000 1000，表示用二補數格式的有號二進製表示法，其中小數位數是 7 位元（縮放係數是 1128），至少要用 15 位元來儲存（確保實際範圍可以從 12800 到將近 12800）。 Q 格式是由德州儀器定義的。用 Qf 來表示有 f 位小數的有號定點數，例如 Q15 是縮放係數為 1215 的二補數有號數。而 Qmf 額外的標示數字的整數部份有 m 位（不算符號位元）。因此 Q130 表示有一位整數，30 位小數的二進制定點數，可以存在 32 位元二補數整數中，縮放係數是 1230。ARM 架構也有類似的標示法，但其中的 m 有包括符號位元，因此上述的格式要改為 Q230。 公司用 fxmb 來表示共有 b 位元，小數有 m 位元的二進制定點數，因此是 b 位元的整數，縮放係數是 12bm。因此 fx116 是十六位元數字，整數部份 1 位元，小數部份 15 位元。 PlayStation 2 GS（Graphics Synthesizer）使用者指南中用 smf 的標示方式，其中 s 表示是否有符號位元。例如，053 表示 8 位元整數，縮放係數是 123 的無號數。 LabVIEW 程式語言的標示方式是 sbm，表示 FXP 定點數的格式。s 可以是 或 ，表示無號數或是二補數的有號數。b 是總位元個數，而 m 是整數部份的位數。 軟體應用例 常用的 TrueType 字型格式，在一些指令中，使用 32 位元的有號二進制定點數，來表達數值。這個格式是在考慮字型微調以及效能下，可以提供最小精度的格式。 Sony 原生 PlayStation 和世嘉土星的所有 3D 計算引擎、任天堂的 Game Boy Advance（其中的二維計算機圖形）、任天堂 DS（2D 和 3D）、任天堂 GameCube 及 GP2X Wiz 電子遊戲系統，這些系統沒有浮點運算器，都使用定點運算。PlayStation 中的轉換協處理器中有硬體支援 16 位元的浮點運算，其中有 12 位的小數。 廣為科學界和數學界使用的 TeX 軟體，在所有位置的運算中，使用 32 位元有號二進制定點數運算，其小數位數是 16 位。這個值的單位長度對應印刷中的點。TeX font metric 檔案使用 32 位元定點數，其中有 12 位小數。 、和都是軟體的函式庫，可以針對 Vorbis、和 MP3 的聲音檔。這些解碼都使用定點運算，因為許多解碼硬體中沒有浮點運算器。 WavPack 無損聲音壓縮器也是使用定點運算。此決定有一部份是擔心不同硬體中對於浮點數的捨入規則差異會破壞壓縮器的無損特性。 Nest Labs Utilities library 提供少量針對定點數的巨集以及函式，特別是用在處理和感測器取樣以及感測器輸出有關的數字。 OpenGL ES 1x 規格中包括定點數，因為這是針對嵌入式系統的 API，不一定有浮點運算器。 Dc 和 Bc 程式都是高精度計算計算器，但只支擾（使用者定義的）定點小數。 表達數字的方式類似 Q 格式的定點數，可以加速在 Intel 80386 或 Intel 80486SX 等沒有浮點運算器的舊電腦。 毀滅戰士是 Id Software 所出的第一人稱射擊遊戲，其非整數運算（例如地圖系統、地理、算繪、玩家移動等）都是用 1616 的定點格式。為了相容性考量，此表達法仍用在現代的 Doom source port 中。 有時在儲存或處理影像或是影像幀時，會使用定點數。有單指令流多資料流單元，主要針對影像處理的處理器，一般都有適用於定點數的指令。 Microsoft Azure 量子計算機的 Q Sharp 程式語言，是實現量子閘用的語言，其中包括標準的數值函式庫，可以在量子位元暫存器上處理定點運算。 相關條目 Q 格式 浮點數 計算機編碼 誤差、數值修約 ：C 語言的定點數函式庫 迷你浮點數 模除 參考文獻 Category 計算機算術 Category 資料型別