To run embedded in a website, add the following html:
<script src="//onlinegdb.com/embed/js/ByP5zKVCZ"></script>
// 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>
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.
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;
}
'
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;
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.
Your code always output with the wrong answers. You should check your code again.