Skip to content

Instantly share code, notes, and snippets.

@JohannesMP
Last active September 14, 2022 02:14
Show Gist options
  • Save JohannesMP/a911b7dc02bb0586e3111a0cbd2dc0e2 to your computer and use it in GitHub Desktop.
Save JohannesMP/a911b7dc02bb0586e3111a0cbd2dc0e2 to your computer and use it in GitHub Desktop.
Converting a number from one base to another in C++
// NOTE: For the sake of practice, STL/stdlib helpers are not used, just std::string for memory management.
#include <string>
using std::string;
// Convert arbitrary base to base 10
// - Input must be valid number in the given base
// - Base must be between 2 and 36
// - If input or base are invalid, returns 0
long ConvertTo10(const string& input, int base)
{
if(base < 2 || base > 36)
return 0;
bool isNegative = (input[0] == '-');
int startIndex = input.length()-1;
int endIndex = isNegative ? 1 : 0;
long value = 0;
int digitValue = 1;
for(int i = startIndex; i >= endIndex; --i)
{
char c = input[i];
// Uppercase it - NOTE: could be done with std::toupper
if(c >= 'a' && c <= 'z')
c -= ('a' - 'A');
// Convert char to int value - NOTE: could be done with std::atoi
// 0-9
if(c >= '0' && c <= '9')
c -= '0';
// A-Z
else
c = c - 'A' + 10;
if(c >= base)
return 0;
// Get the base 10 value of this digit
value += c * digitValue;
// Each digit has value base^digit position - NOTE: this avoids pow
digitValue *= base;
}
if(isNegative)
value *= -1;
return value;
}
// Convert base 10 to arbitrary base
// - Base must be between 2 and 36
// - If base is invalid, returns "0"
// - NOTE: this whole function could be done with itoa
string ConvertFrom10(long value, int base)
{
if(base < 2 || base > 36)
return "0";
bool isNegative = (value < 0);
if(isNegative)
value *= -1;
// NOTE: it's probably possible to reserve string based on value
string output;
do
{
char digit = value % base;
// Convert to appropriate base character
// 0-9
if(digit < 10)
digit += '0';
// A-Z
else
digit = digit + 'A' - 10;
// Append digit to string (in reverse order)
output += digit;
value /= base;
} while (value > 0);
if(isNegative)
output += '-';
// Reverse the string - NOTE: could be done with std::reverse
int len = output.size() - 1;
for(int i = 0; i < len; ++i)
{
// Swap characters - NOTE: Could be done with std::swap
char temp = output[i];
output[i] = output[len-i];
output[len-i] = temp;
}
return output;
}
// Convert from one base to another
string ConvertBase(const string& input, int baseFrom, int baseTo)
{
// NOTE: There is probably a more efficient way to convert between two bases.
// This however is easy to understand and debug.
return ConvertFrom10(ConvertTo10(input, baseFrom), baseTo);
}
#include <iostream>
using std::cout;
using std::endl;
int main()
{
// Bases 10 and 2 (positive)
cout << "===== 1 =====" << endl;
cout << ConvertBase("101", 2, 10) << endl; // 100(2) = 5(10)
cout << ConvertBase("5", 10, 2) << endl; // 5(10) = 101(2)
// Bases 10 and 16 (negative)
cout << "===== 2 =====" << endl;
cout << ConvertBase("-1A", 16, 10) << endl; // -1A(16) = -26(10)
cout << ConvertBase("-26", 10, 16) << endl; // -26(10) = -1A(16)
// Bases 5 and 7
cout << "===== 3.1 =====" << endl;
cout << ConvertBase("100", 5, 10) << endl; // 100(5) = 25(10)
cout << ConvertBase("25", 10, 7) << endl; // 25(10) = 34(7)
// So therefore...
cout << "===== 3.2 =====" << endl;
cout << ConvertBase("100", 5, 7) << endl; // 100(5) = 34(7)
cout << ConvertBase("34", 7, 5) << endl; // 34(7) = 100(5)
// Larger Bases (26, 13)
cout << "===== 4 =====" << endl;
cout << ConvertBase("1234", 26, 13) << endl; // 1234(26) = 8864(13)
cout << ConvertBase("8864", 13, 26) << endl; // 8864(13) = 1234(26)
return 0;
}

To run embedded in a website, add the following html:

<script src="//onlinegdb.com/embed/js/ByP5zKVCZ"></script>
@trailcode
Copy link

The ConvertFrom10 function does not work for base 4:
http://www.unitconversion.org/numbers/base-10-to-base-4-conversion.html
Try: 558947203 base 10

@PikarryPham
Copy link

Your code always output with the wrong answers. You should check your code again.

@JohannesMP
Copy link
Author

JohannesMP commented Dec 13, 2019

Your code always output with the wrong answers. You should check your code again.

Thank you for taking the time to reply. This code has not been rigorously tested, and is inefficient. It was never intended to be more than a toy exercise, for one small set of values where it fulfilled my needs at the time, which is why it is a gist and not a proper git repo.

I would strongly recommend using alternatives that have been rigorously unit tested and not to rely on random gists, especially if you seek to write production-quality code.

That being said, if you would like to contribute something constructive, please provide some example values where it doesn’t not work, or - what would be even more useful - recommend a code change or create a fork that would fix the incorrect behaviour you alluded to.

As it stands, my time is unfortunately quite limited right now so I cannot promise that I will revisit this any time soon.

@samarth-bhargav
Copy link

samarth-bhargav commented May 5, 2020

The issue is in the reverse algorithm. Here is working code for anyone interested.
'

string ConvertFrom10(long value, int base)
{
if(base < 2 || base > 36)
return "0";

bool isNegative = (value < 0);
if(isNegative)
    value *= -1;

// NOTE: it's probably possible to reserve string based on value
string output;

do
{
    char digit = value % base;

    // Convert to appropriate base character
    // 0-9
    if(digit < 10)
        digit += '0';
        // A-Z
    else
        digit = digit + 'A' - 10;

    // Append digit to string (in reverse order)
    output += digit;

    value /= base;

} while (value > 0);

if(isNegative)
    output += '-';

// Reverse the string - NOTE: could be done with std::reverse
reverse(output.begin(), output.end());
return output;

}
'

@lec-Geisel
Copy link

lec-Geisel commented May 18, 2022

You should probably build the output string in reverse order. e.g. instead of:
output += digit;
try:
output = digit + output;

P.S.
You will also have to do the same for the sign.
output += '-';
Should be:
output = '-' + output;

@qdeanc
Copy link

qdeanc commented Sep 14, 2022

You should probably build the output string in reverse order. e.g. instead of: output += digit; try: output = digit + output;

P.S. You will also have to do the same for the sign. output += '-'; Should be: output = '-' + output;

I actually don't recommend doing this.

output = digit + output;
and even
output = output + digit;
Are both significantly slower operations than
output += digit;
when it comes to the std string data type.

Meanwhile, std:reverse is actually extremely performant.
So it's ultimately faster to build strings in reverse order using += and then reverse them using std::reverse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment