關於大數除法


最近在九度oj上看了幾個關於大數的問題,特意在這里總結一番。

要知道我們要將一個1000多位的十進制數轉換為二進制數,是沒有哪個類型能裝得下的,所以在這里我們的手動模擬輾轉相除法。實現將一個很長的十進制數字符串轉換成二進制的字符數組。

首先我們來看看這些int,long等等的取值范圍,明白它們到底可以存多大,我們才能放心到底什么時候可以用,什么時候不可以用。

 

數據類型名稱 字節數 別名 取值范圍
int * signed,signed int 操作系統決定,即與操作系統的"字長"有關
unsigned int * unsigned 由操作系統決定,即與操作系統的"字長"有關
__int8 1 char,signed char –128 到 127
__int16 2 short,short int,signed short int –32,768 到 32,767
__int32 4 signed,signed int –2,147,483,648 到 2,147,483,647
__int64 8 –9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
bool 1 false 或 true
char 1 signed char –128 到 127
unsigned char 1 0 到 255
short 2 short int,signed short int –32,768 到 32,767
unsigned short 2 unsigned short int 0 到 65,535
long 4 long int,signed long int –2,147,483,648 到 2,147,483,647
long long 8 none (but equivalent to __int64) –9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
unsigned long 4 unsigned long int 0 到 4,294,967,295
enum * 由操作系統決定,即與操作系統的"字長"有關
float 4 3.4E +/- 38 (7 digits)
double 8 1.7E +/- 308 (15 digits)
long double 8 1.7E +/- 308 (15 digits)
wchar_t 2 __wchar_t 0 到 65,535

 

 

 

類型標識符 類型說明 長度
(字節)
范圍 備注
char 字符型 1 -128 ~ 127 -27 ~ (27 -1)
unsigned char 無符字符型 1 0 ~ 255 0 ~ (28 -1)
short int 短整型 2 -32768 ~ 32767 2-15 ~ (215 - 1)
unsigned short int 無符短整型 2 0 ~ 65535 0 ~ (216 - 1)
int 整型 4 -2147483648 ~ 2147483647 -231 ~ (231 - 1)
unsigned int 無符整型 4 0 ~ 4294967295 0 ~ (232-1)
float 實型(單精度) 4 1.18*10-38 ~ 3.40*1038 7位有效位
double 實型(雙精度) 8 2.23*10-308 ~ 1.79*10308 15位有效位
long double 實型(長雙精度) 10 3.37*10-4932 ~ 1.18*104932 19位有效位

 


 

具體的轉換思想(轉載):在數據結構課關於棧的這一章中,我們都學過用“模2取余法”來將一個10進制數轉換為一個二進制數,進而可以推廣到“模n取余法”,經其轉換為n進制(n任意指定)。

確實,這是一個很基礎的題目,可你是否想過如果這個10進制數是一個大數(其位數可能上千位,此時用一般數據類型肯定是會溢出的),那么這個問題又如何來求解呢?

當然,也許你會說很簡單嘛,自己寫一個大數類(當然至少要寫一個大數除法才行),或者你用的是Java這種現代化語言,就更輕松了,直接用BigInteger這樣的大數類就可以來表示一個大數,進而用書上教的方法來實現。

但是,真的需要用到大數類嗎?事實上,“殺雞焉用牛刀“,我們在紙上模擬一番上述運算后就可以發現,只要做一些小小的改進,就可以在不使用大數的情況下,也可以通過“模n

取余”的原理來實現大數的進制轉換的。(當然,整體的思想仍然是“模n取余”原理!!!)。

舉個簡單的例子,就比如說把10進制數12轉換為2進制形式,書上的方法可以用下圖來表示

按照 “先余為低位,后余為高位“這條鐵律,其結果為1100.

這是書上教我們的常規思路(可惜按這個的話,大數是沒法考慮的,因為假如這里不是12,而是一個1000位的大數,由於是是對大數的整體進行取余運算,不使用大數類及其

除法操作,又如何得以進行呢?),可我們的目的是不使用大數類,那么現在我們就來換一個視角來看這個問題,12是一個十位數,十位上是1,個位上是2,按照我們正常的

思維來看,這個計算應該是下面這樣的:

那么我們發現在第一輪運算時,十位上的1作為被除數,2作為除數,得到的商是0,余數是1(可以斷言只考慮當前這一個數位的計算,余數或是0,或是1,若是1的話,則進

下一數位(這里即對個位進行運算)時,要用1乘上進制(這里是10)再加上下一個數位上的值(這里是2)),即得到運算進入個位時被除數是12,除數是2,得到的商是6,

數是0。第一輪運算的結果是商是06,余數是0.

進入第二輪運算,則上一輪的商6(這里首先要去掉前面多余的0)變成本輪的被除數,如此下去,即可得到每輪的余數。

推廣開來,如果被除數是一個1000位的大數,例如“12343435154324123……342314324343”

那么我們照樣可以從第一個數位開始逐位考慮,比如第一位是1(作為被除數),2是除數,得到的商是0,余數是1,然后是第二個數位2,由於上一位留下了余數1,則此時被

除數應該是1*10+2 = 12,所以得到的商是6,余數是0,即運算到此時的商是06,然后是第三個數位3,由於上一個數位留下的余數是0,所以此時被除數就是3,。。。如此下去

就完成第一輪的運算,這一輪完畢后,需要把得到的商變成下一輪的被除數,繼續上述的運算,直到被除數為0才停止。

 


 1 /*題目1138:進制轉換
 2 題目描述:
 3 將一個長度最多為30位數字的十進制非負整數轉換為二進制數輸出。
 4 */
 5 #include "stdafx.h"
 6 #pragma warning(disable:4996)
 7 #include <stdio.h>
 8 #include <cstring>
 9 #include <string>
10 #include <iostream>
11 using namespace std;
12 char binvec[1001];
13 
14 
15 void tenToBin(string str)  
16 {  
17     int j=0;
18     int sum=1;
19     int len=str.size();
20 
21     while (sum)
22     {
23         sum=0;
24         for (int i=0;i<len;++i)
25         {
26             int temp=(str[i]-'0')/2;
27             sum+=temp;
28             if (i==len-1)
29             {
30                 binvec[j++]=(str[i]-'0')%2+'0';
31             }else
32             {
33                 str[i+1]=str[i+1]+(str[i]-'0')%2*10;//算出下一個被除數
34             }
35             //記錄該次得出的商
36             str[i]=temp+'0';
37         }
38     }
39     
40 
41 } 
42 void resout()
43 {
44     //逆序
45     int len1=strlen(binvec);
46     for (int i=0,j=len1-1;i<len1/2;++i,--j)
47     {
48         char temp=binvec[j];
49         binvec[j]=binvec[i];
50         binvec[i]=temp;
51     }
52     cout<<binvec<<endl;
53 }
54 int main()
55 {
56     string str;
57     while(cin>>str)
58     {
59         memset(binvec,'\0',sizeof(binvec));
60         tenToBin(str);
61         resout();
62     }
63     return 0;
64 }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM