您的位置:首页 > 其它

字符串加减法(整数,小数)

2013-09-12 13:32 127 查看
最近在做华为的机试题的时候发现有字符串的小数减法,在百度知道上又看到有人问字符串减法的问题,于是也想练练手。

#ifndef _STRING_OPS_H_
#define _STRING_OPS_H_

//[left, right),翻转字符串
void string_swap(char* input, size_t left, size_t right)
{
for (; left < --right; left++)
{//
if (input[left] != input[right])
{//
char t = input[left];
input[left] = input[right];
input[right] = t;
}
}
}

//找到字符串中的小数点
size_t find_dot(const char* str)
{
size_t pos = (size_t)-1;
for (pos = 0; pos < strlen(str); pos++)
{//
if (str[pos] == '.')
{//
break;
}
}

return pos;
}

//str1+str2
//首先只简单考虑全是正数的情况
int two_positive_integer_add(const char* str1, size_t len1,
const char* str2, size_t len2,
char* out, size_t& olen,
int carry = 0/*用于小数加法的传递*/)
{
int res; //两个数相加的结果
size_t ptr1 = len1-1, ptr2 = len2-1;
olen = len1 > len2 ? len1+1 : len2+1;
size_t p = olen-1;
for (size_t ptr = len1 < len2 ? len1 : len2;
ptr > 0; ptr1--, ptr2--, ptr--, p--)
{//
res = str1[ptr1] - '0' + str2[ptr2] - '0' + carry;
carry = res>9;
res = carry ? res-10: res;
out[p] = res+'0';
}

//把剩余的位数相加
for (; ptr1 != (size_t)-1; ptr1--, p--)
{//
res = str1[ptr1] - '0' + carry;
carry = res>9;
res = carry ? res-10: res;
out[p] = res+'0';
}
for (; ptr2 != (size_t)-1; ptr2--, p--)
{//
res = str2[ptr2] - '0' + carry;
carry = res>9;
res = carry ? res-10: res;
out[p] = res+'0';
}
int shift = 0;
//把carry加上
if (carry == 1)
{//
out[p--] = '1';
}
else
{
olen -= 1;
for (p = 0; p < olen; p++)
{//
out[p] = out[p+1];
}
shift = 1;
}
return shift;
}

//小数部分相加
//返回整数部分相加时需要的carry
int two_positive_fraction_add(const char* str1, size_t len1,
const char* str2, size_t len2,
char* out, size_t& olen)
{
int carry = 0;

size_t left = len1 < len2 ? len1 : len2; //取最短的那个的末尾
size_t right = len1 > len2 ? len1 : len2; //取最长的那个的末尾
const char* longer = len1  > len2 ? str1 : str2;
//把left,right之间的部分直接复制给out
olen = right;
size_t p = olen-1;
for (--left; --right != left;)
{//
out[p--] = longer[right];
}

//把两个字符串相加
int res;
for (; left != (size_t)-1; --left)
{//
res = str1[left] - '0' + str2[left] - '0' + carry;
carry = res>9;
res = carry ? res-10: res;
out[p--] = res+'0';
}
//看看末尾的0
while (olen != 0 && out[olen-1] == '0')
{//
olen--;
}
if (olen == 0)
{//两个数相等。
out[olen++] = '0';
}
//carry可能是1也可能是0
return carry;
}

void two_positive_add(const char* str1, const char* str2, char* out)
{
size_t dot_pos1 = find_dot(str1);
size_t dot_pos2 = find_dot(str2);

//计算小数部分
int carry = 0;
size_t olen_fraction = 0;
if (dot_pos1 < strlen(str1) || dot_pos2 < strlen(str2))
{//
char* fraction = out + (dot_pos1 > dot_pos2 ? dot_pos1+1 : dot_pos2+1);
fraction[0] = '.';
fraction++;
size_t pos1 = dot_pos1 != strlen(str1) ? dot_pos1+1 : dot_pos1;
size_t pos2 = dot_pos2 != strlen(str2) ? dot_pos2+1 : dot_pos2;
carry = two_positive_fraction_add(str1+pos1, strlen(str1)-pos1,
str2+pos2, strlen(str2)-pos2, fraction, olen_fraction);
}

//计算整数部分
size_t olen_integer;
int shift = two_positive_integer_add(str1, dot_pos1, str2, dot_pos2,
out,  olen_integer, carry);

//左移小数部分
if (shift > 0)
{//
size_t olen = olen_integer + olen_fraction + 1;
for (size_t p = olen_integer; p < olen; p++)
{//
out[p] = out[p+shift];
}
}
out[olen_fraction + olen_integer + 1] = '\0';
}

//str1-str2
//两个数全是正数,且str1>str2
int two_positive_integer_minus(const char* str1, size_t len1,
const char* str2, size_t len2,
char* out, size_t& olen, int borrow = 0)
{
int res; //两个数相减的结果
size_t ptr1 = len1-1, ptr2 = len2-1;
int a,b;//被减数,减数
olen = len1 > len2 ? len1 : len2;
size_t p = olen-1;
for (; ptr2 != (size_t)-1; ptr1--, ptr2--, p--)
{//
a = str1[ptr1]-'0' - borrow;
b = str2[ptr2] - '0';
borrow = a < b ? 1 : 0;
res = a + 10*borrow - b;

out[p] = res+'0';
}

//把剩余的位数相减
for (; ptr1 != (size_t)-1; ptr1--, p--)
{//
a = str1[ptr1]-'0' - borrow;
borrow = a < 0 ? 1 : 0;
res = a + 10*borrow;

out[p] = res+'0';
}
//删除开头的0
size_t zeros = 0;
for (p = 0; p < olen; p++)
{//
if (out[p] != '0')
{//
break;
}
zeros++;
}
if (zeros > 0)
{//
if (zeros == olen)
{//
olen = 1;
out[0] = '0';
zeros -= 1;
}
else
{
olen -= zeros;
for (p = 0; p < olen; p++)
{//
out[p] = out[p+zeros];
}
}
}

return zeros;
}

//小数部分相减str1-str2
//返回整数部分相加时需要的carry
int two_positive_fraction_minus(const char* str1, size_t len1,
const char* str2, size_t len2,
char* out, size_t& olen)
{
olen = 0;
int borrow = 0;
size_t left = len1 < len2 ? len1 : len2; //取最短的那个的末尾
size_t right = len1 > len2 ? len1 : len2; //取最长的那个的末尾
const char* longer = len1  > len2 ? str1 : str2;
olen = right;
size_t p = olen-1;
int a, b, res;

if (longer == str2)
{//短-长
for (--left; --right != left;)
{//
a = 0 - borrow;
b = longer[right] - '0';
borrow = a < b;
res = a+10*borrow - b;
out[p--] = res + '0';
}
}
else
{//长-短
for (--left; --right != left;)
{//
out[p--] = longer[right];
}
}

for (; left != (size_t)-1; left--)
{//
a = str1[left] - '0' - borrow;
b = str2[left] - '0';
borrow = a < b;
res = a+10*borrow - b;
out[p--] = res + '0';
}

//把最后的0去掉
p = olen-1;
for (; p != (size_t)-1; p--)
{//
if (out[p] != '0')
{//
break;
}
}
olen = p == (size_t)-1 ? 1 : p+1;
return borrow;
}

//str1 > str2
void two_positive_minus(const char* str1, const char* str2, char* out)
{
size_t dot_pos1 = find_dot(str1);
size_t dot_pos2 = find_dot(str2);

//计算小数部分
int borrow = 0;
size_t olen_fraction = 0;
if (dot_pos1 < strlen(str1) || dot_pos2 < strlen(str2))
{//
char* fraction = out + dot_pos1;
fraction[0] = '.';
fraction++;
size_t pos1 = dot_pos1 != strlen(str1) ? dot_pos1+1 : dot_pos1;
size_t pos2 = dot_pos2 != strlen(str2) ? dot_pos2+1 : dot_pos2;
borrow = two_positive_fraction_minus(str1+pos1, strlen(str1)-pos1,
str2+pos2, strlen(str2)-pos2, fraction, olen_fraction);
}

//计算整数部分
size_t olen_integer;
int shift = two_positive_integer_minus(str1, dot_pos1, str2, dot_pos2,
out,  olen_integer, borrow);

//左移小数部分
if (shift > 0)
{//
size_t olen = olen_integer + olen_fraction + 1;
for (size_t p = olen_integer; p < olen; p++)
{//
out[p] = out[p+shift];
}
}
out[olen_fraction + olen_integer + 1] = '\0';
}

//str1 > str2 ?
//str1和str2都是正数
const bool two_positive_is_larger(const char* str1, const char* str2)
{
size_t dot_pos1 = find_dot(str1);
size_t dot_pos2 = find_dot(str2);

if (dot_pos1 > dot_pos2)
{//12345 > 1234
return true;
}
if (dot_pos1 < dot_pos2)
{//123 < 3456
return false;
}

//整数部分等长
for (size_t ptr = 0; ptr != dot_pos1; ptr++)
{//
if (str1[ptr] != str2[ptr])
{//
if (str1[ptr] > str2[ptr])
{//123456 > 122456
return true;
}
//123456 < 124456
return false;
}
}

//整数部分相同,那么比较小数部分
size_t len1 = strlen(str1), len2 = strlen(str2);
dot_pos1++, dot_pos2++;
for (; dot_pos1 < len1 && dot_pos2 < len2; dot_pos1++, dot_pos2++)
{//
if (str1[dot_pos1] != str2[dot_pos2])
{//
if (str1[dot_pos1] > str2[dot_pos2])
{//
return true;
}
//
return false;
}
}

//前面的相等
if (dot_pos2 < len1)
{//str1的长度比较长,所以返回str1
return false;
}

return true;
}

//假设str1和str2的输入都符合要求,out有足够的空间存储
//str如果为正,那么开头无符号,若为负,则开头需要有-号
void minu(const char* str1, const char* str2, char* out)
{
bool neg = false;
if (*str1 == '-' && *str2 == '-')
{//|str2|-|str1|
if (two_positive_is_larger(str1+1, str2+1))
{//|str1|>|str2|,那么由于是|str2|-|str1|,结果为负
two_positive_minus(str1+1, str2+1, out);
}
else
{
two_positive_minus(str2+1, str1+1, out);
}
return;
}

if (*str1 != '-' && *str2 != '-')
{//|str1|-|str2|
if (two_positive_is_larger(str1, str2))
{//|str1|>|str2|,那么由于是str1-str2,结果为正
two_positive_minus(str1, str2, out);
}
else
{
two_positive_minus(str2, str1, out);
}
return;
}

if (*str1 == '-' && *str2 != '-')
{//-(|str1| + |str2|)
two_positive_add(str1+1, str2, out);
return;
}

if (*str1 != '-' && *str2 == '-')
{//|str1| + |str2|
two_positive_add(str1, str2+1, out);
return;
}
}

//假设str1和str2的输入都符合要求,out有足够的空间存储
//str如果为正,那么开头无符号,若为负,则开头需要有-号
void ad(const char* str1, const char* str2, char* out)
{
bool neg = false;
if (*str1 == '-' && *str2 != '-')
{//|str2|-|str1|
if (two_positive_is_larger(str1+1, str2))
{//|str1|>|str2|,那么由于是|str2|-|str1|,结果为负
two_positive_minus(str1+1, str2, out);
}
else
{
two_positive_minus(str2, str1+1, out);
}

return;
}

if (*str1 != '-' && *str2 == '-')
{//|str1|-|str2|
if (two_positive_is_larger(str1, str2+1))
{//|str1|>|str2|,那么由于是str1-str2,结果为正
two_positive_minus(str1, str2+1, out);
}
else
{
two_positive_minus(str2+1, str1, out);
}
return;
}

if (*str1 == '-' && *str2 == '-')
{//-(|str1| + |str2|)
two_positive_add(str1+1, str2+1, out);
return;
}

if (*str1 != '-' && *str2 != '-')
{//|str1| + |str2|
two_positive_add(str1, str2, out);
return;
}
}

#endif


 

调用函数为ad和minu,假设输入都正确。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐