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

#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,假设输入都正确。

字符串加减法(整数,小数)相关推荐

  1. python 把带小数的浮点型字符串转换为整数的解决方案

    python 把带小数的浮点型字符串转换为整数的解决方案 参考文章: (1)python 把带小数的浮点型字符串转换为整数的解决方案 (2)https://www.cnblogs.com/mlgjb/ ...

  2. 2021-10-20:分数到小数。给定两个整数,分别表示分数的分子numerator和分母denominator,以字符串形式返回小数。如果小数部分为循环小数,则将循环的部分括在括号内。输入: num

    2021-10-20:分数到小数.给定两个整数,分别表示分数的分子numerator和分母denominator,以字符串形式返回小数.如果小数部分为循环小数,则将循环的部分括在括号内.输入: num ...

  3. oracle 字符转整数,Oracle中字符串转换函数小数转法

    Oracle中字符串转换函数小数转法 类别:Oracle数据库   作者:码皇   来源:薛凯博客     点击: Oracle中字符串转换函数小数转法 to_char()函数的字符串转换格式归纳如下 ...

  4. python爬虫开发 从入门到实战 pdf 谢乾坤_python字符串和整数相互转换的实例分享...

    python 字符串和整数的转换方法 数字转成字符串 方法一: 使用格式化字符串: tt=322 tem='%d' %tt tem即为tt转换成的字符串 常用的格式化字符串: %d 整数 %f%F 浮 ...

  5. js 字符串加减法_基于字符串的数值之加减乘除JS算法研究

    在我们的日常js项目中,我们不免会碰到需要进行前端计算的场景.而大家都知道,计算机进行计算时存在精度问题,且数值有值域,偶尔会碰到溢出问题.在最近的一个项目中,由于遇到了一个超过20位的数,因此,又不 ...

  6. 【卡法 常用 ckl.js 库】: js汇合 表单验证 cookie设置 日期格式 电话手机号码 email 整数 小数 金额 检查参数长度...

    [卡法 常用js库]: js汇合 表单验证  cookie设置  日期格式  电话手机号码  email  整数  小数  金额   检查参数长度 // +---------------------- ...

  7. 数据结构与算法:13 字符串与整数集合

    13 字符串与整数集合 知识点: 1. 字符串 我们古人没有电影电视,没有游戏网络,所以文人们就会想出一些文字游戏来娱乐.比如宋代的李禺写了这样一首诗:"枯眼望遥山隔水,往来曾见几心知?壶空 ...

  8. C++实现字符串和整数之间的相互转换

    参考:http://www.cnblogs.com/GL-BBL/archive/2012/08/19/2646467.html http://www.cnblogs.com/bluestorm/p/ ...

  9. 【剑指offer-Java版】49把字符串转换为整数

    字符串转换为整数 : atoi 可能的输入: 1 带符号数 2 无符号数 3 零 4 空指针 5 超出表示范围 – 暂时仅仅是直接退出且设置最小 – 可以考虑此时抛个异常 6 非法输入,比如并不是一个 ...

最新文章

  1. MySQL介绍与语言结构
  2. 【深度学习入门到精通系列】医学图像预处理—CLAHE变换代码
  3. vue_组件_监听组件事件
  4. Go--4大基本数据类型之布尔类型
  5. Docker 搭建java+tomcat
  6. 先天性异常或智力残疾儿童患者的外显子组和基因组测序:美国医学遗传学与基因组学学院循证临床指南...
  7. ICCV2021 |优胜劣汰,MIT团队提出自适应多模态选取框架用于视频理解
  8. 作为window对象属性的元素 多窗口和窗体
  9. Angular - ng-repeat高级用法
  10. linux登录指令 pgsql_命令行方式登录PostgreSQL
  11. 英语学习—每天进步一丢丢系列(一)
  12. 代码高亮与美化的工具
  13. Mac数据图表软件|让你的论文数据更加直观漂亮
  14. 查看本地计算机ip命令,如何用DOS命令查看自己的IP地址
  15. (1.5.1.3)编程之美:一摞烙饼的排序
  16. 企业破产清算中几个难题的探析(转)
  17. 优达学城,基于激光的卡尔曼滤波器的C++实现。
  18. 【Java案例】购书系统(超详细)
  19. 《1Q84》--[日]村上春树
  20. 屏幕距离和坐便转换工具_投影幕尺寸计算、投影距离计算、观影距离计算

热门文章

  1. ScaleAnimation类:尺寸变化动画类
  2. C/C++判断文件/文件夹的状态:文件存在与否、读权限、写权限、执行权限
  3. java.lang.NoClassDefFoundError: org/apache/poi/xwpf/usermodel/IRunBody异常
  4. python小技巧:获取字典中值最大者的key 1
  5. epoll模型实现及惊群效应
  6. 【pacing 1】PACER模块、PacedSender 及关键参数
  7. 【Linux编程环境】mount虚拟机ssh登录跳转路径
  8. DPDK无锁队列之MemPool理解
  9. vue-photo-preview踩坑,el-table中一张错误图片导致全部图片无法放大,并且与懒加载v-lazy不兼容
  10. 如何在keynote画渐变色线条