简体   繁体   中英

Hexadecimal Calculator for Addition and Subtraction

I have an issue with my program which is used to calculate addition and subtraction for Hexadecimals. The algorithm of my program is:

  • Take 2 strings inputted by the user, and "+" or "-" depending on the operator they chose
  • Convert the 2 strings into decimals, and add or subtract
  • If the second number is bigger, use the bigger number to subtract the smaller number, and put a "-" in front of it when returning the result (1 - 8 should = -7, but instead, I take 8 - 1 = 7, and return "-" and "7" so it gives "-7)
  • Take the decimal result from the operation and convert back to hexadecimal
  • Return string of hexadecimal

However, I have run into a issue where my calculations give me wrong answers. (For eg FFFFFF + FFFFFFFFFF prints "FFFFFFE" instead of "10000FFFFFE")

What can I do to solve the issue?

I created my own Power function for this program as I need aa number that can go up to 16 Fs for the Hexadecimal string.

Power Function:

unsigned long long int result = 1;
int i;

for (i = 0; i < y; i++)
{
    result *= x;
}

return result;

Code:

int i;
int power = FirstHexaNumber.length() - 1;
int power2 = SeconHexaNumber.length() - 1;
int checkLength = FirstHexaNumber.length();
int checkLength2 = SeconHexaNumber.length();
unsigned long long int decimalNumber = 0;
unsigned long long int decimalNumber2 = 0;
unsigned long long int totalDecimal;
int temporary;
string result;

if (Operator == '+')                            //check if operator is add or minus
{
    //Convert Hex to Decimal for first number

    for (i = 0; i < checkLength; i++)
    {
        if (int(FirstHexaNumber[i]) >= 48 && int(FirstHexaNumber[i]) <= 57) {       // check if FirstHexaNumber 0 to 9

            decimalNumber += ((int(FirstHexaNumber[i])) - 48) * powerFunc(16, power);   //formula to convert hexadecimal into decimal, int(FirstHexaNumber[i]) is used to convert hexa into a number
        }
        else if (int(FirstHexaNumber[i]) >= 65 && int(FirstHexaNumber[i]) <= 70)    // check if FirstHexaNumber is A to F
        {
            decimalNumber += ((int(FirstHexaNumber[i])) - 55)*powerFunc(16, power);
        }
        else if (int(FirstHexaNumber[i]) >= 97 && int(FirstHexaNumber[i]) <= 102)   // check if FirstHexaNumber is a to f
        {
            int x = powerFunc(16, power);
            decimalNumber += ((int(FirstHexaNumber[i])) - 87)* x;
        }
        power--;            //power-- since it starts from "HexaNumber.length - 1". Power should decrease as assignment of power goes down
    }

    //Convert Hex to Decimal for second number

    for (i = 0; i < checkLength2; i++)
    {
        if (int(SeconHexaNumber[i]) >= 48 && int(SeconHexaNumber[i]) <= 57) {

            decimalNumber2 += ((int(SeconHexaNumber[i])) - 48) * powerFunc(16, power2);     //formula to convert Hexadecimal to Decimal
        }
        else if (int(SeconHexaNumber[i]) >= 65 && int(SeconHexaNumber[i]) <= 70)
        {
            decimalNumber2 += ((int(SeconHexaNumber[i])) - 55)*powerFunc(16, power2);       //formula to convert Hexadecimal to Decimal
        }
        else if (int(SeconHexaNumber[i]) >= 97 && int(SeconHexaNumber[i]) <= 102)
        {
            unsigned long long int x = powerFunc(16, power2);
            decimalNumber2 += ((int(SeconHexaNumber[i])) - 87)*x;       //formula to convert Hexadecimal to Decimal
        }
        power2--;
    }

    totalDecimal = decimalNumber + decimalNumber2;                                  //Adds the total decimal to convert into hexadecimal

    if (totalDecimal == 0)
    {
        return "0";
    }

    //Converts Decimal to Hexadecimal
    for (i = 0; totalDecimal != 0; i++)             //as long as totalDecimal does not hit 0 from being divided by 16, run the loop
    {
        temporary = totalDecimal % 16;              //use temporary as a variable to temporarily hold onto the number remainder of mod 16

        if (temporary >= 10)                        //if temporary >= 10, that means it needs to be converted to alphabet
        {
            result.insert(0, 1, temporary + 55);    //result.insert inserts a string of text into a spot, and pushes everything else backwards.
        }                                           //in this case, result.insert assigns "temporary+55" into the spot of characters 0 to 1.

        else                                        //else, it means that the decimal will be a number, add 48 to convert to ascii          
        {
            result.insert(0, 1, temporary + 48);
        }
        totalDecimal = totalDecimal / 16;           //divide by 16 to move on to finding the next digit/alphabet
    }

    return result;
}
else if (Operator == '-')                           //check if operator is add or minus
{
    //Convert Hex to Decimal for first number

    for (i = 0; i < checkLength; i++)               //as long as the loop does not exceed the length of the hexadecimal, run it
    {
        if (int(FirstHexaNumber[i]) >= 48 && int(FirstHexaNumber[i]) <= 57) {

            decimalNumber += ((int(FirstHexaNumber[i])) - 48) * powerFunc(16, power);
        }
        else if (int(FirstHexaNumber[i]) >= 65 && int(FirstHexaNumber[i]) <= 70)
        {
            decimalNumber += ((int(FirstHexaNumber[i])) - 55)*powerFunc(16, power);
        }
        else if (int(FirstHexaNumber[i]) >= 97 && int(FirstHexaNumber[i]) <= 102)
        {
            decimalNumber += ((int(FirstHexaNumber[i])) - 87)*powerFunc(16, power);
        }
        power--;    
    }

    //Convert Hex to Decimal for second number

    for (i = 0; i < checkLength2; i++)
    {
        if (int(SeconHexaNumber[i]) >= 48 && int(SeconHexaNumber[i]) <= 57) {

            decimalNumber2 += ((int(SeconHexaNumber[i])) - 48) * powerFunc(16, power2);
        }
        else if (int(SeconHexaNumber[i]) >= 65 && int(SeconHexaNumber[i]) <= 70)
        {
            decimalNumber2 += ((int(SeconHexaNumber[i])) - 55)*powerFunc(16, power2);
        }
        else if (int(SeconHexaNumber[i]) >= 97 && int(SeconHexaNumber[i]) <= 102)
        {
            decimalNumber2 += ((int(SeconHexaNumber[i])) - 87)*powerFunc(16, power2);
        }
        power2--;
    }

    if (decimalNumber >= decimalNumber2)
    {
        totalDecimal = decimalNumber - decimalNumber2;          //subtract bigger number by smaller number.

        if (totalDecimal == 0)
        {
            return "0";
        }

        for (i = 0; totalDecimal != 0; i++)
        {
            temporary = totalDecimal % 16;

            if (temporary >= 10)
            {
                result.insert(0, 1, temporary + 55);
            }
            else
            {
                result.insert(0, 1, temporary + 48);
            }
            totalDecimal = totalDecimal / 16;
        }

        return result;
    }
    else
    {
        totalDecimal = decimalNumber2 - decimalNumber;          //subtract bigger number by smaller number.

        if (totalDecimal == 0)
        {
            return "0";
        }

        for (i = 0; totalDecimal != 0; i++)
        {
            temporary = totalDecimal % 16;

            if (temporary >= 10)
            {
                result.insert(0, 1, temporary + 55);
            }
            else
            {
                result.insert(0, 1, temporary + 48);
            }
            totalDecimal = totalDecimal / 16;
        }

        return "-" + result;
    }

}
return 0;

You can try this snippet:

int a,b;
cout << "\nEnter A in hex: ";
cin >> hex >> a;
cout << "\nEnter B in hex: ";
cin >> hex >> b;
cout << "\n Addition of " << hex << a <<" and "<< hex << b << " is " << hex << a+b;
cout << "\n Substraction of " << hex << a << " and " << hex << b << " is " << hex << a - b;

int x = powerFunc(16, power); should be long long x = powerFunc(16, power); Don't know full source of the function pow , the return type should be long long too.

Hexadecimal Calculator can be more simple.

#include <sstream>
std::stringstream ss1(s1),ss2(s2);
ss1 >> std::hex >> i1;
ss2 >> std::hex >> s2;

std::cout << std::hex << std::uppercase << i1 + s2 << std::endl;

std::stringstream res;
res << std::hex << std::uppercase << i1 + i2;
return res.str();

According to a magical wizard (well uh, programmer ) like me, this magical function shall grant your wish:-

Note: The source code(s) not copied from any sources.

std::tuple<std::vector<std::string>, std::vector<char>> DistributeHexStringToStrings(std::string Target)
{
    std::string::size_type n1 = 0;
    while ((n1 = Target.find(std::string(" "), n1)) != std::string::npos)
    {
        Target.replace(n1, std::string(" ").size(), "");
        n1 += std::string("").size();
    }
    if (Target.find("--") != std::string::npos || Target.find("++") != std::string::npos ||
        Target.find("-+") != std::string::npos || Target.find("+-") != std::string::npos)
        throw std::invalid_argument("You should not use double signs!");
    std::string::size_type n2 = 0;
    while ((n2 = Target.find(std::string("-"), n2)) != std::string::npos)
    {
        Target.replace(n2, std::string("-").size(), "+-");
        n2 += std::string("+-").size();
    }
    std::vector<char> TermOperator;
    if (Target[0] != '+' && Target[1] != '-')
        TermOperator.emplace_back('+');
    for (auto i = 0; i < signed(Target.size()); i++)
        if (Target[i] == '+' && Target[i + 1] != '-')
            TermOperator.emplace_back('+');
        else if (Target[i] == '+' && Target[i + 1] == '-')
            TermOperator.emplace_back('-');
        else if (!(Target[i] >= '0' && Target[i] <= '9' || Target[i] >= 'A' && Target[i] <= 'F' ||
            Target[i] >= 'a' && Target[i] <= 'f' || Target[i] == '+' || Target[i] == '-'))
            throw std::invalid_argument("The specified hexadecimal expression is not valid!");
    const size_t Terms = std::count(Target.begin(), Target.end(), '+') + 1;
    std::stringstream HexStream(Target);
    std::vector<std::string> HexStrings;
    for (auto i = 0; i < signed(Terms); i++)
    {
        std::string Temporary;
        std::getline(HexStream, Temporary, '+');
        if (Temporary.empty() || Temporary == "-" || Temporary == "+")
            continue;
        HexStrings.emplace_back(Temporary);
    }
    return std::make_tuple(HexStrings, TermOperator);
}

This function will distribute the strings in the cleanest possible way. But the work is still undone, we need to use this function properly to get our desired result, and what I have here is another function that can do the conversion of the hex strings to real hex numbers:-

std::vector<long long> ConvertHexaDecimalToDecimal(std::vector<std::string> HexStrings)
{
    std::vector<long long> HexValues;
    for (auto &elem : HexStrings)
    {
        if (elem[0] == '-')
            elem.erase(elem.begin());
        int Temporary;
        std::stringstream HexConverter(elem);
        HexConverter >> std::hex >> Temporary;
        if (Temporary == 0)
            continue;
        HexValues.emplace_back(Temporary);
    }
    return HexValues;
}

This function will convert all the hexadecimal string values to real decimal equivalents of the hex numbers, now we need to calculate it like this:-

long long CalculateHexadecimalExpression(std::vector<long long> &HexValues, std::vector<char> &Operators)
{
    if (Operators.size() != HexValues.size())
        throw std::invalid_argument("Operators and Number of Hex Values do not match!");
    long long Result = 0;
    for (auto i = 0; i < signed(Operators.size() & HexValues.size()); i++)
    {
        switch (Operators[i])
        {
        case '+':
            Result += HexValues[i];
            break;
        case '-':
            Result -= HexValues[i];
            break;
        default: break;
        }
    }
    return Result;
}

This function will do all the resulting calculations for you.

Now you can use these three functions together to yield the desired result you wanted.

Example:-

int main()
{
    const std::string Example = "3 + 2";
    std::vector<std::string> HStrings;
    std::vector<char> HOperators;
    std::tie(HStrings, HOperators) = DistributeHexStringToStrings(Example);
    auto HNumbers = ConvertHexaDecimalToDecimal(HStrings);
    std::cout << ConvertDecimalToHexaDecimalValue(CalculateHexadecimalExpression(HNumbers, HOperators)) << std::endl;
}

Output:-

3855

Note: If you want, you could go one step further and convert the resulting number to a hex too (using this function):-

std::string ConvertDecimalToHexaDecimalValue(const long long Hex, bool UpperCase = true)
{
    std::stringstream HexResultStream;
    HexResultStream << (Hex < 0 ? "-" : "") << (UpperCase ? std::uppercase : std::nouppercase) << std::hex << abs(Hex);
    return HexResultStream.str();
}

And use it like this, ConvertDecimalToHexaDecimalValue(CalculateHexadecimalExpression(HNumbers, HOperators)) .

Which will give you F0F , assign a value to the second parameter as false to yield the hexadecimal string in lowercase. ( eg, ConvertDecimalToHexaDecimalValue(CalculateHexadecimalExpression(HNumbers, HOperators, false ));

Don't forget to add these includes to the top:-

#include <iostream>
#include <vector>
#include <sstream>
#include <tuple>

Regards from a fellow programmer,

Ruks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM