关于大数除法

最近在九度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 }
时间: 2024-10-17 02:15:18

关于大数除法的相关文章

2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)

题目链接 分析:打表以后就能发现时卡特兰数, 但是有除法取余. f[i] = f[i-1]*(4*i - 2)/(i+1); 看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展gcd, 不是用逆元吗.. 网上还有别人的解释,没看懂,贴一下: (a / b) % m = ( a % (m*b)) / b 笔者注:鉴于ACM题目特别喜欢M=1000000007,为质数: 当gcd(b,m) = 1, 有性质: (a/b)%m = (a*b^-1)%m, 其中b^-1是b模m的逆

组合数学 + 大数乘法 + 大数除法 之 hdu 1261 字串数

//  [3/17/2015 JmingS] /* 此题可直接推导出公式: {(A1+A2+……+An)!} / {A1!A2!……An!} 由于 (12×26)! = 312! 只能通过数组来存储,所以又涉及『大数乘法』和『大数除法』, 大数实现的主要思想模拟手算,具体参考程序. */ 1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5

51 Nod 1029 大数除法【Java大数乱搞】

1029 大数除法 基准时间限制:4 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 给出2个大整数A,B,计算A / B和A Mod B的结果. Input 第1行:大数A 第2行:大数B (A,B的长度 <= 100000,A,B >= 0) Output 第1行:A / B 第2行:A Mod B (A % B) Input示例 987654321 1234 Output示例 800368 209 题目链接:http://www.51nod.com/onlineJud

二进制转换 ——大数除法

1132: 数据结构习题--使用栈实现进制转换 时间限制: 1 Sec  内存限制: 128 MB 提交: 15  解决: 9 [提交][状态][讨论版] 题目描述 使用栈将一个很长(>30)的十进制数转换为二进制数 输入 若干个很长的十进制数 每行一个 输出 转换为二进制,每行输出一个 样例输入 123456789012345678901234567890 753951684269875454652589568545854758545824 样例输出 110001110111010010000

高精度之大数除法

大数除法说的比较少或许不像加法减法那样简单,或许是用的不太多.到底怎么我也不知道. 反正你会了加法减法,乘法而不会除法,就像是,打开电脑而不玩游戏,心里难受. 我是从看到了大神博客后学习了一下. http://blog.csdn.net/hitwhylz/article/details/9700935 博客中讲的很详细 让人一看就懂,我很佩服这位同学.果断的关注了. 毕竟别人写的是别人的. 自己写的才是自己的 .于是我就捋了捋,模仿这写了一遍: 思想就是:用减法来代替除法,但是一次一次的减太慢,

大数除法(lld最多19位)

大数除法的核心:把除法运算转化为减法运算,根据除法运算的特点, 有两个大整数a和b,当a==b时,a/b==1,余数是0.(a!=0,b!=0) 当a>b时,a/b>=1,余数需要通过计算求得. 当a<b时,a/b=0,余数就是a. 以7546除23为例. 先减去23的100倍,就是2300,可以减3次,余下646.   此时商就是300: 然后646减去23的10倍,就是230,可以减2次,余下186.此时商就是320: 然后186减去23,可以减8次,此时商就是328. 特例 本题要

poj2325 大数除法+贪心

将输入的大数除以9 无法整除再除以 8,7,6,..2,如果可以整除就将除数记录,将商作为除数继续除9,8,...,3,2. 最后如果商为1 证明可以除尽 将被除过的数从小到大输出即可 #include<cstdio> #include<cstring> #define mem(a) memset(a,0,sizeof (a)) using namespace std; char s[1005], t[1005]; int bang[15], n; bool div(int p)

hdu 1261 排列组合&amp;&amp;大数除法

唉  不知道第一次发什么神经 第一次把t定义成char 型的了 小数还对 大数就不多了...找了半个小时才找到  以后要细心了 求大数 一定是用字符串保存,,long long 肯定溢出. 具体思路就是把所有字符个数加起来的阶乘n!除以各个字符出现的个数的阶乘. #include <stdio.h> #include <string.h> #define num 1000 int main() { char str[num]; long long n,x,count,j,i,q,s

(母函数 Catalan数 大数乘法 大数除法) Train Problem II hdu1023

Train Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10372    Accepted Submission(s): 5543 Problem Description As we all know the Train Problem I, the boss of the Ignatius Train Sta