問題描述:
兩個任意長度的正數相減,這兩個正數可以帶小數點,也可以是整數,請輸出結果。 輸入的字符串中,不會出現除了數字與小數點以外的其它字符,不會出現多個小數點以及小數點在第一個字符的位置等非法情況,所以考生的程序中無須考慮輸入的數值字符串非法的情況。
詳細要求以及約束:
1.輸入均爲正數,但輸出可能爲負數;
2.輸入輸出均爲字符串形式;
3.如果輸出是正數則不需要帶符號,如果爲負數,則輸出的結果字符串需要帶負號
例如:2.2-1.1 直接輸出爲“1.1”,1.1-2.2 則需要輸出爲“-1.1”
4.輸出的結果字符串需要過濾掉整數位前以及小數位後無效的0,小數位爲全0的,直接輸出整數位
例如相減結果爲11.345,此數值前後均不可以帶0,“011.345”或者“0011.34500”等等前後帶無效0的均視爲錯誤 輸出。例如1.1-1.1結果爲0.0,則直接輸出0。
要求實現函數:
void Decrease(char *input1, char*input2, char *output)
【輸入】 char *iinput1 被減數
char*nput2 減數
【輸出】 char *output 減法結果
【返回】 無
示例
輸入:char *input1="2.2"
char *input2="1.1"
輸出:char*output="1.1"
輸入:char *input1="1.1"
char *input2="2.2"
輸出:char *output="-1.1"
以上摘自 http://blog.csdn.net/lanyan822/article/details/7983832 ,但是考慮到沒有給出這個的源代碼,自己隨手寫了一個,寫得不好,僅供娛樂,歡迎大神指點。
這次的代碼很長,我是爲了寫的可讀性更高一點,很多地方比較累贅而且用的方法比較直接,也是我一開始直接想到的。如果有更好的方法希望大家提供哈...
//正數減法
//問題描述:
//兩個任意長度的正數相減,這兩個正數可以帶小數點,也可以是整數,請輸出結果。
//輸入的字符串中,不會出現除了數字與小數點以外的其它字符,不會出現多個小數點以及小數點在第一個字符的位置等非法情況,所以考生的程序中無須考慮輸入的數值字符串非法的情況。
//詳細要求以及約束:
//1.輸入均爲正數,但輸出可能爲負數;
//2.輸入輸出均爲字符串形式;
//3.如果輸出是正數則不需要帶符號,如果爲負數,則輸出的結果字符串需要帶負號
//例如:2.2-1.1 直接輸出爲“1.1”,1.1-2.2 則需要輸出爲“-1.1”
// 4.輸出的結果字符串需要過濾掉整數位前以及小數位後無效的0,小數位爲全0的,直接輸出整數位
//例如相減結果爲11.345,此數值前後均不可以帶0,“011.345”或者“0011.34500”等等前後帶無效0的均視爲錯誤 輸出。例如1.1-1.1結果爲0.0,則直接輸出0。
//要求實現函數:
//void Decrease(char *input1, char*input2, char *output)
//【輸入】 char *iinput1 被減數
//char*nput2 減數
//【輸出】 char *output 減法結果
//【返回】 無
//示例
//輸入:char *input1="2.2"
//char *input2="1.1"
//輸出:char*output="1.1"
//輸入:char *input1="1.1"
//char *input2="2.2"
//輸出:char *output="-1.1"
#include <algorithm>
#include <assert.h>
//得到小數點的位置
int getDot(char *input1)//小數點計算函數
{
return find(input1,input1+strlen(input1),'.') - input1;
}
void Decrease(char *input1, char*input2, char *output)
{
assert(input1 != NULL && input2 != NULL && output != NULL);//假設三個參數都不爲空
//1.小數點對其
int dot1 = getDot(input1),dot2 = getDot(input2);
//2.小數點對其初始化兩個char數組,方便之後運算。長度爲雙方可能的最大位數
int length = ((strlen(input1)-dot1)>(strlen(input2)-dot2)?(strlen(input1)-dot1):(strlen(input2)-dot2))/*小數部分最長的值*/
+(dot1>dot2?dot1:dot2)/*整數部分最長的值*/+1/*可能產生的符號位與小數點*/;
char *str1,*str2,*result;
str1 = (char *)malloc(length+1);//加1爲了存結束符
str2 = (char *)malloc(length+1);
result = (char *)malloc(length+1);
memset(str1,'0',length);
memset(str2,'0',length);
memset(result,'0',length);
str1[length] = '\0';
str2[length] = '\0';
result[length] = '\0';
//3.得出每個字符串小數點對其後的位置,但是不拷貝最後一個'\0'結束符
memcpy(&str1[abs(dot1>dot2?dot1:dot2-dot1)+1],input1,strlen(input1));
memcpy(&str2[abs(dot1>dot2?dot1:dot2-dot2)+1],input2,strlen(input2));
//4.得到兩數之間較大的數,爲了保證始終大數減小數,省的借位情況複雜
int isPlus = true;//如果被減數更大則爲真
char *max = str1,*min = str2;
for(int i = 1;i < length;++i)
{
if(str1[i] > str2[i])
{
max = str1;
min = str2;
break;
}
else if(str1[i] < str2[i])
{
isPlus = false;
max = str2;
min = str1;
break;
}
else if(i == length - 1)
{//兩個字符串數字相等
output[0] = '0';
output[1] = '\0';
return ;
}
}
//把沒有小數點的全部補齊
result[dot1>dot2?dot1:dot2 + 1] = '.';
max[dot1>dot2?dot1:dot2 + 1] = '.';
min[dot1>dot2?dot1:dot2 + 1] = '.';
//5.開始運算
for(int i = length-1;i > 0;--i)
{//開始從右到左開始減
if(max[i] == '.')
{
result[i] == '.';
continue;
}
int temp;
temp = max[i] - min[i];
if(temp < 0)
{//如果不夠減時向高位借數
int j = i;
while(max[j] == '0' || max[j] == '.'/* && j != 0*/)
{//找到可以借位的數爲止,因爲輸入的都是整數,所以不做更多討論
if(max[j] == '0')
{
max[j] = '9';
}
j--;
}
max[j]--;
temp += 10;
}
result[i] = temp + '0';
}
if(!isPlus)
output[0] = '-';
//6.把結果字符格式化給output字符串
for(unsigned int i = strlen(result);i >= 0;++i)
{//清除末尾0或最後一位是小數點
if(result[i] == '0' || result[i] == '.')
result[i] = '\0';
else
break;
}
unsigned int first = 1;//記錄第一位有效位的起始位置
while(result[first] == '0')
{
first++;
}
strcpy(output,&result[first]);
}
int _tmain(int argc, _TCHAR* argv[])
{
char r[10000];
Decrease("2.2", "1.1",r);
cout<<r;
return 0;
}