简体   繁体   中英

Conver BCD Strings to Decimal

I am looking for better ways to optimize this function for better performance, speed its targeted towards embedded device. i welcome any pointers, suggestion thanks

function converts string BCD to Decimal

int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
    int NumSubstrings = str.length() / splitLength;
    std::vector<std::string> ret;
    int newvalue;

    for (auto i = 0; i < NumSubstrings; i++)
    {
        ret.push_back(str.substr(i * splitLength, splitLength));
    }

    // If there are leftover characters, create a shorter item at the end.
    if (str.length() % splitLength != 0)
    {
        ret.push_back(str.substr(splitLength * NumSubstrings));
    }

    string temp;

    for (int i=0; i<(int)ret.size(); i++)
     {
         temp +=ReverseBCDFormat(ret[i]);
     }

    return newvalue =std::stoi(temp);

}

string ReverseBCDFormat(string num)
{

    if( num == "0000")
    {
        return "0";
    }
    else if( num == "0001")
    {
        return "1";
    }
    else if( num == "0010")
    {
        return "2";
    }
    else if( num == "0011")
    {
        return "3";
    }
    else if( num == "0100")
    {
        return "4";
    }
    else if( num == "0101")
    {
        return "5";
    }
    else if( num == "0110")
    {
        return "6";
    }
    else if( num == "0111")
    {
        return "7";
    }
    else if( num == "1000")
    {
        return "8";
    }
    else if( num == "1001")
    {
        return "9";
    }
    else
    {
        return "0";

    }

}

Update this is what i plan to get, for a BCD Value:: 0010000000000000 Decimal Result 2000

BCD is a method of encoding decimal numbers, two to a byte.

For instance 0x12345678 is the BCD representation of the decimal number 12345678. But, that doesn't seem to be what you're processing. So, I'm not sure you mean BCD when you say BCD.

As for the code, you could speed it up quite a bit by iterating over each substring and directly calculating the value. At a minimum, change ReverseBCDFormat to return an integer instead of a string and calculate the string on the fly:

temp = temp * 10 + ReverseBCDFormat(...)

Something like that.

What you call BCD is not actually BCD.

With that out of the way, you can do this:

int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
    int ret = 0;
    for (unsigned i = 0, n = unsigned(str.size()); i < n; )
    {
        int v = 0;
        for (unsigned j = 0; j < splitLength && i < n; ++j, ++i)
            v = 2*v + ('1' == str[i] ? 1 : 0); // or 2*v + (str[i]-'0')
        ret = 10*ret + v;
    }
    return ret;
}

Get rid of all the useless vector making and string copying. You don't need any of those.

Also, I think your code has a bug when processing strings with lengths that aren't a multiple of splitLength . I think your code always considers them to be zero. In fact, now that I think about it, your code won't work with any splitLength other than 4 .

BTW, if you provide some sample inputs along with their expected outputs, I would be able to actually verify my code against yours (given that your definition of BCD differs from that of most people, what your code does is not exactly clear.)

as soon as you're optimizing function, here is different variant:

int ConvertBCDToDecimal(const std::string& str) {
    unsigned int result = 0;
    const std::string::size_type l = str.length();
    for (std::string::size_type i = 0; i < l; i += 4)
        result = result * 10 + ((str[i] - '0') << 3) + ((str[i + 1] - '0') << 2) + ((str[i + 2] - '0') << 1) + (str[i + 3] - '0');
    return result;
}

note: you don't need splitLength argument, as you know that every digit is 4 symbols

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