阿里2018实习生笔试题——大数相加

2018年5月份的在线编程笔试题第一题,投递岗位C++后台开发。

题目描述

两个大数使用string 表示,请实现一个函数,将他们相加。
注意:
1. 大数可能包含小数,比如:123.07+8796
2. 输入可能有误,请检查是否合法,不合法返回值为false
3. 大数不包含科学计数法。

思路

  1. 检查string是否合法;不合法返回“false”。
  2. 分离string,分成整数部分和小数部分。
  3. 对整数部分进行加法,先对齐补零。
  4. 对小数部分进行加法,先对齐补零。
  5. 负数情况如何处理?转化为大数减法。先判断哪个是作为被减数。

测试用例

空,+,-,.5,+345,-234;

code

#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
// 正负数判断
bool isPositive(string number) // number合法情况下
{
    if (number[0] == '-')
        return false;
    return true;
}
// 是否合法
bool isNumber(string number)// 空,+,-不合法
{
    int len = number.size();
    if (len <= 0)
        return false;
    int i = 0;
    if ((number[i] == '+' || number[i] == '-') && len > 1)
    {
        i++;
    }
    while (number[i] != '.'&&i < len)
    {
        if (number[i]<'0' || number[i]>'9')
            return false;
        i++;
    }
    if (number[i] == '.')
    {
        i++;
        while (i < len)
        {
            if (number[i]<'0' || number[i]>'9')
                return false;
            i++;
        }
    }
    if (i == len)
        return true;
    return false;
}
// getting inter and decimal by '.'
bool gettingInterDecimal(string number, string &inter, string &decimal)
{
    int position = number.find('.');
    inter = number.substr(0, position);
    if (position < number.size())
        decimal = number.substr(position + 1, number.size());
    return true;
}
string addAlign(string &add1, string &add2, int right, bool &carry) // right=1,mean 右对齐加;else 左对齐加
{

    while (add2.size() < add1.size())
    {
        if (!right)
            add2 += '0';
        else
            add2 = '0' + add2;
    }
    while (add1.size() < add2.size())
    {
        if (!right)
            add1 += '0';
        else
            add1 = '0' + add1;
    }
    bool carryadd = 0;
    string addsum = add1;
    for (int i = add1.size()-1; i >= 0; i--)
    {
        addsum[i] = add1[i] + add2[i] + carryadd-'0';
        if (addsum[i] > '9')
        {
            addsum[i] -= 10;
            carryadd = 1;
        }
        else
            carryadd = 0;
    }
    carry = carryadd;
    return addsum;
}
bool cmpNumber(string inter1, string inter2, string decimal1, string decimal2)
{
    if (inter1.size() != inter2.size())
        return inter1.size() > inter2.size();
    if (inter1.compare(inter2) != 0)
        return inter1.compare(inter2)>=0;
    return decimal1.compare(decimal2)>=0;
}
string subAlign(string &sub1, string &sub2, int right,bool &carry) // right=1,mean 右对齐加;else 左对齐加
{
    while (sub1.size() < sub2.size()) // sub1 less means decimal
        sub1 += '0';
    while (sub2.size() < sub1.size())
    {
        if(!right)
            sub2 += '0';
        else
            sub2 = '0'+sub2;
    }
    string sub=sub1;
    bool carrysub = 0;
    for (int i = sub2.size() - 1; i >= 0; i--)
    {
        sub[i] = sub1[i] - sub2[i] + '0'-carrysub;
        if (sub[i] < '0')
        {
            carrysub = 1;
            sub[i] += 10;
        }
        else
            carrysub = 0;
    }
    carry = carrysub;
    return sub;
}
string stringadd(string add1, string add2)
{
    string sum;
    bool isnumber = (isNumber(add1) && isNumber(add2));
    if (!isnumber)
        return "false";
    bool add1sign = isPositive(add1);
    bool add2sign = isPositive(add2);
    if (add1[0] == '+' || add1[0] == '-')
        add1.erase(0,1);
    if (add2[0] == '+' || add2[0] == '-')
        add2.erase(0,1);
    string add1inter, add1de;  // for integer and decimal
    string add2inter, add2de;
    gettingInterDecimal(add1, add1inter, add1de);
    gettingInterDecimal(add2, add2inter, add2de);
    if (add1sign == add2sign)  // 同为正数和同为负数情况
    {
        bool carry1, carry2;
        string decimalsum = addAlign(add1de, add2de, 0, carry2);
        if (carry2)
        {
            if (add1inter.size() > 0)
                add1inter[add1inter.size() - 1] += carry2;
            else
                add1inter = "1";
        }
        string intersum = addAlign(add1inter, add2inter, 1, carry1);
        if (carry1)
            intersum = '1' + intersum;
        sum = intersum + "." + decimalsum;
        if (!add1sign)
            sum = '-' + sum;
    }
    else// 一个正数和一个负数情况,转化为减法,大数减小数
    {
        bool add1more = cmpNumber(add1inter, add2inter, add1de, add2de);
        if (add1more)
        {
            bool carry;
            string subdecimal = subAlign(add1de, add2de, 0,carry);
            if(carry)
                add1inter[add1inter.size() - 1] -= 1;
            string subinter = subAlign(add1inter, add2inter,1, carry);
            sum = subinter + "." + subdecimal;
            if (!add1sign)
                sum = "-" + sum;
        }
        else
        {
            bool carry;
            string subdecimal = subAlign(add2de, add1de, 0,carry);
            if(carry)
                add2inter[add2inter.size() - 1] -= 1;
            string subinter = subAlign(add2inter, add1inter, 1,carry);
            sum = subinter + "." + subdecimal;
            if (!add2sign)
                sum = "-" + sum;
        }
    }
    return sum;
}
void test()
{
    string sum;
    cout << stringadd(".89", "0.11") << endl;
    cout << sum << endl;
    cout << stringadd("123", "-456") << endl;
    cout << sum << endl;
}

reference

另一种运算符重载思路 可参考
https://blog.csdn.net/to_be

猜你喜欢

转载自blog.csdn.net/ytang_/article/details/80339338