闲着没事干,帮别人写个c语言的作业,就顺便用来写这博客好了。
题目是用字符串来表示浮点数(字符串长度为30,后10位是小数位),实现加减乘除法。我觉得这和大数类似,用char来表示一个数字,虽然有点浪费空间,不过优化,思路不变就无关紧要了,思路对了就行。
由于我的懒惰和她们老师并不要求写浮点数除法,我也就没写了,正负数的判断也没写,内存释放也没写,怕内存泄漏的话就后面自己free就好了也没多难,因为她们题目要求返回char *所以我malloc之后就没free。然后读取数据也比较简单,我也不能不让她什么偶不写嘛,所以我就没写获取数据,scanf就行,也没多难。
ps:我的程序是把第20位作为整数的个位,19位是十位。。。第21位就是小数的第一位,22是小数第二位。。。
加减法没有难点,乘法难点是在相乘后的数字所在的位数,除法的难点就是取余然后放到它该在的位置上,余数继续往后算。就这样。
#include<stdio.h>
#include<memory.h>
#include<stdlib.h>
#include<string>
bool biger_then(const char* a, const char *b) {
//大小判断
int temp = 0;
while (a[temp] == '0'&&b[temp] == '0' || a[temp] == b[temp]) temp++;
if (a[temp] - b[temp] > 0)
return true;
else
return false;
}
char * getnum(char *result,int flag) {
//将结果整合成人们习惯的表达式
char *p = (char *)malloc(31);
memset(p, 0, 31);
int i = 0, j = 0;
if (flag == 0)
j = 0;
else {
p[j++] = '-';
}
while (result[i] == '0' && i < 20)
i++;
while (i < 20)
p[j++] = result[i++];
if (p[0] == 0 &&flag==0 || p[1]== 0 && flag == 1 )
p[j++] = '0';
p[j++] = '.';
while (i < 30)
p[j++] = result[i++];
p[j] = '\0';
return p;
}
void creatnum(char *input) {
//将字符串改成要求的格式
char p[30];
for (int i = 0; i < 30; i++)
p[i] = '0';
if (input == NULL)
return;
int point=0;
while (input[point]!='\0'){
if (input[point] >= '0'&&input[point] <= '9' || input[point] == '.') {
if (input[point] != '.')
point++;
else
break;
}else{
printf("input error");
return;
}
}
int i = point - 1, j = 19;
char temp = '0';
for (; i >= 0&&j >= 0; j--, i--)
p[j] = input[i];
for (i = point + 1, j = 20; input[i] != '\0'&&j < 30; j++, i++)
p[j] = input[i];
for (i = 0; i < 30; i++)
input[i] = p[i];
input[30] = '\0';
}
char * add(const char *a, const char *b) {
//两个符合要求的字符串的加法,懒得拓展字符串加整数了
if (b == NULL || a == NULL) {
printf("input error\n");
exit(1);
}
char result[31];
for (int i = 0; i < 30; i++)
result[i] = '0';
result[30] = '\0';
int add_flag = 0;
for (int i = 29; i >= 0; i--) {
int temp = a[i] - '0' + b[i] - '0' + add_flag;
if (temp > 9) {
temp -= 10;
add_flag += 1;
}
else
add_flag = 0;
result[i] = temp + '0';
}
return getnum(result,0);
}
char * sub(const char *a, const char *b){
//两个符合要求的字符串的减法,同样懒得拓展字符串减整数了
if (b == NULL || a == NULL) {
printf("input error\n");
exit(1);
}
char result[31];
const char *p, *q;
for (int i = 0; i < 30; i++)
result[i] = '0';
result[30] = '\0';
int flag = 0,j;
if (biger_then(a,b)) {
p = a;
q = b;
}else{
p = b;
q = a;
flag = 1;
}
for (int i = 0; i < 30; i++) {
if (p[i] - q[i] >= 0)
result[i] = p[i] - q[i] + '0';
else {
j = i - 1;
while (result[j] == '0')
j--;
result[j++]--;
while (j > i);
result[j++] = '9';
result[i] = p[i] - q[i] + 10 + '0';
}
}
return getnum(result,flag);
}
char * div(const char *a, int b) {
//除以整数,小数,因为怕被除数过大给我整越界了,所以就写个简单的字符串除以整数
if (b == 0||a == NULL) {
printf("input error\n");
exit(1);
}
int i, down = 0,flag=0;
if (b < 0) {
flag = 1;
b = -b;
}
char result[31];
for (i = 0; i < 30; i++)
{
result[i] = (a[i] + down * 10 - '0') / b + '0';
down = a[i] - '0' + down * 10 - (result[i] - '0' ) * b;
}
return getnum(result, flag);
}
char * mul(const char *a, const char *b) {
//两个符合要求的字符串的乘法,没错,我还是懒得拓展字符串乘整数了
char temp1[31], temp2[31], result1[31],result2[31];
for (int i = 0; i < 30; i++)
temp1[i]=result1[i]= temp2[i] = result2[i] = '0';
for (int i = 0; i < 20; i++)
temp1[i] = b[i];
int num = 0;//小数点偏移量。
for (int i = 29; i >= 20; i--) {
if (b[i] != '0') {
int j = 19;
while (i >= 20) {
temp2[j--] = b[i--];
num++;
}
}
}
temp1[30] = temp2[30]= result1[30] = result2[30] = '\0';
int i, j, up, t;
for (i = 29; i >= 0; i--) { //整数部分
up = 0;
for (j = 19; j >= 0; j--) {
t = (a[i] - '0')*(temp1[j] - '0') + (result1[i + j - 19]-'0') + up;
if (t >= 10) {
up = t / 10;
if(i + j - 19 >=0&& i + j - 19 < 30)
result1[i + j - 19] = t % 10 + '0';
}
else {
up = 0;
if (i + j - 19 >= 0 && i + j - 19 < 30)
result1[i + j - 19] = t + '0';
}
}
}
for (i = 29; i >= 0; i--) { //小数部分
up = 0;
for (j = 19; j >= 0; j--) {
t = (a[i] - '0')*(temp2[j] - '0') + (result2[i + j - 19] - '0') + up;
if (t >= 10) {
up = t / 10;
if (i + j - 19 >= 0 && i + j - 19 < 30)
result2[i + j - 19] = t % 10 + '0';
}
else {
up = 0;
if (i + j - 19 >= 0 && i + j - 19 < 30)
result2[i + j - 19] = t + '0';
}
}
}
//对小数部分的结果进行偏移。
for (int i = 29; i >= 0; i--) {
if (i + num < 30) {
result2[i + num] = result2[i];
result2[i] = '0';
}
}
//将result1和result2合起来就是结果,调用加法函数。
return add(result1, result2);
}
int main()
{
//没有进行输入负数字符串的判断,只进行了正数的合法性输入的判断。
//这个没有释放heap上的内存,容易导致内存泄漏,一般情况得自己释放
char i[31] = "2.2";
char j[31] = "0.3";
printf("a=%s b=%s\n", i,j);
creatnum(i);
creatnum(j);
printf("a + b = %s\n", p);
p = sub(i, j);
printf("a - b = %s\n", p);
p = mul(i, j);
printf("a * b = %s\n", p);
int t=-3;
char *q = div(i, t);
printf("a / %d = %s\n", t ,q);
if (biger_then(i, j))
printf("a>b");
else
printf("a<=b");
return 0;
}
不太会说话,这就是个思路的问题实现起来难度并不大,语言难度挺小的。小数除法我还是不太会算。。。有空再研究吧