程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> 處理超長位數的數

處理超長位數的數

編輯:關於C

 

float和double型數據分別是單精度和雙精度型數,他們的取值分別是3.4E+10的負38次方到3.4E+10的38次方,和1.7E+10的負308次方到1.7E+10的308次方。

那麼float 6-7位的有效數字怎麼能裝下如3.4E+10的負38次方同是double型婁15-16位的有效數字怎麼能裝下如1.7E+10的負308次方的數呢。這不是相矛盾嗎?

 

回答:不矛盾。float 6-7位 指的是 有效數字的位數(精度) 而不是 數值 大小。例如,3.14159267有9位有效數字,數值卻在3~4之間,而350有3位數字,大小卻在300~400之間。所以說float數能達到3.4E+10,但是它的有效數字位數只能達到6-7位,如果3.14159267賦值給一個float變量,那麼精度將會減小。例如

float a=3234567.1;

float b=3234567;

if( a==b )

    printf("YES");

else

    printf("NO");

將輸出YES,因為a末尾的11超出了float 只能達到6-7位的精度。(如果a=1234567.1;b=3234567)輸入結果將是NO,為什麼呢?這就要我們分析:超出精度的部分怎麼處理?不是四捨五入,而是二進制位的丟失。所以說有時候能達到6位的精度,有時候能達到7位的精度,取決於該數的二進制表示。

 

那麼我們就想怎麼表示超長位數,超大精度的數字呢?比如123456789123456789123456789(超長30位的大整數),比如3.14159012345678901234567890123(超高精度30位的小數),這麼長的數字,long float都存不下來,這就要借助於“字符串”或者“字符數組”了。

unsigned __int64 n;

無符號__int64類型的變量n,最大值超過了1234567892345678912(20位),可達到約1.8E+19,平常來說應該夠用了。__int64類型的數據不能用C++裡面的cout來輸出,應該是cout沒有重載這個類型,如果用printf來輸出,顯然%d, %f, %l都無法滿足20位的精度,網上查到VC6下可以用printf("%I64d\n", n);但是支持的位數不超過20,經我測試,大概超過9.23E+18 輸出的結果就會出錯了。那麼最好的辦法是將“長位數”轉換成字符串,如下:

char buffer[65];

printf("%s", _ui64toa(n, buffer,10) );

函數_ui64toa就是負責將n轉換成字符串的,存入字符數組buffer[65]中,10代表轉換成10進制。

 轉換數字為字符串:

 

#include <stdlib.h> 

#include <stdio.h> 

int main( void ) 

   char buffer[65]; 

   int r; 

   for( r=10; r>=2; --r ) 

   { 

     _itoa( -1, buffer, r ); 

     printf( "base %d: %s (%d chars)\n", r, buffer, strlen(buffer) ); 

   } 

   printf( "\n" ); 

   for( r=10; r>=2; --r ) 

   { 

     _i64toa( -1L, buffer, r ); 

     printf( "base %d: %s (%d chars)\n", r, buffer, strlen(buffer) ); 

   } 

   printf( "\n" ); 

   for( r=10; r>=2; --r ) 

   { 

     _ui64toa( 0xffffffffffffffffL, buffer, r ); 

     printf( "base %d: %s (%d chars)\n", r, buffer, strlen(buffer) ); 

   } 

 

 

Output 

base 10: -1 (2 chars) 

base 9: 12068657453 (11 chars) 

base 8: 37777777777 (11 chars) 

base 7: 211301422353 (12 chars) 

base 6: 1550104015503 (13 chars) 

base 5: 32244002423140 (14 chars) 

base 4: 3333333333333333 (16 chars) 

base 3: 102002022201221111210 (21 chars) 

base 2: 11111111111111111111111111111111 (32 chars) 

 

base 10: -1 (2 chars) 

base 9: 145808576354216723756 (21 chars) 

base 8: 1777777777777777777777 (22 chars) 

base 7: 45012021522523134134601 (23 chars) 

base 6: 3520522010102100444244423 (25 chars) 

base 5: 2214220303114400424121122430 (28 chars) 

base 4: 33333333333333333333333333333333 (32 chars) 

base 3: 11112220022122120101211020120210210211220 (41 chars) 

base 2: 1111111111111111111111111111111111111111111111111111111111111111 (64 chars) 

 

base 10: 18446744073709551615 (20 chars) 

base 9: 145808576354216723756 (21 chars) 

base 8: 1777777777777777777777 (22 chars) 

base 7: 45012021522523134134601 (23 chars) 

base 6: 3520522010102100444244423 (25 chars) 

base 5: 2214220303114400424121122430 (28 chars) 

base 4: 33333333333333333333333333333333 (32 chars) 

base 3: 11112220022122120101211020120210210211220 (41 chars) 

base 2: 1111111111111111111111111111111111111111111111111111111111111111 (64 chars) 

 

PS:可以用這個函數來將10進制整數轉換成二進制字符串;

int main( void )

{

   char buffer[65];

   _itoa( 12, buffer, 2 );

   printf( "base %d: %s (%d chars)\n", r, buffer, strlen(buffer) );

}

 

還有一種方法是自己定義字符數組存放 超長位數的數,小數點也是可以解決的,然後自己定義這些 字符串形式的超長數之間的運算法則並重載運算符,據說這樣做運算效率還是蠻高的。

 

摘自zollty的專欄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved