How to obtain rightmost unset bit position of a number N in c++.
1<= N <= 2^60
storing as number does not work since 2^60 can only be stored in string.
thus following does not work
long long getBitUtil(long long n) {
return log2(n&-n)+1;
}
long long getBit(long long n) {
return getBitUtil(~n);
}
Try this. Code is self explanatory with comments
int getRightmostUnSetBit(string s, int pos)
{
int l= s.size();
int lc = s[l-1];
if(lc>=48 && lc<=57 && lc%2 ==0)
return pos; // if last digit is even return position
else
{// divide the number into half and call function again.
string s2 = "";
int rem =0;
for(int i =0; i<l;i++)
{
int d = s[i]-'0';
d = rem *10 + d;
int q = d/2;
rem = d%2;
s2.push_back('0'+q);
}
return getRightmostUnSetBit(s2,pos+1); //call for s2
}
}
Take input in string and call from main
int pos = getRightmostUnSetBit(s,1);// will not work if s is "0" or similar to "000...". So check for it before function calling.
For normal integers the solution is basically given in the book Hackers Delight. I can only refer to the book. I cannot copy. But section 2.1 gives already good hints.
Depending on your OS you will most likely have 64 bit data types. With 64 bit data types, you can still use arithmentic solutions for your given number range. Above that, you should use string representations.
Then we will convert a big decimal number given as string into a string containing its binary equivalent.
Then we search for the last 0 in the resulting binary string.
The secret is to do a division by 2 for a number given as string. This can be done as we learned in school on a piece of paper.
And then check, if the number is even or odd and put a 1 or 0 respectively in the resulting string.
This will work for abitrary big numbers. Limiting factor (but here not really) is the length of the resulting binary string. That must fit into a std::string :-)
See:
#include <string>
#include <iostream>
#include <bitset>
#include <iterator>
#include <regex>
#include <stack>
#include <algorithm>
// Odd numbers. We will find out, if a digit is odd or even
std::string oddNumbers{ "13579" };
// Devide a number in a string by 2. Just like in school on a piece of paper
void divideDecimalNumberAsStringBy2(std::string& str)
{
// Handling of overflow during devisions
unsigned int nextNumberToAdd{ 0 };
// The resulting new string
std::string newString{};
// Go through all digits, starting from the beginning
for (char& c : str) {
// Get overflow for next round
unsigned int numberToAdd = nextNumberToAdd;
// Get the overflow value for the next devision run. If number is odd, it will be 5
nextNumberToAdd = (oddNumbers.find(c) != std::string::npos) ? 5 : 0;
// Do the devision. Add overflow from last round
unsigned int newDigit = (c - '0') / 2 + numberToAdd;
// Build up newe string
newString += static_cast<char>(newDigit + '0');
}
// Remove leading zeroes
str = std::regex_replace(newString, std::regex("^0+"), "");
}
// Convert a string with a big decimal number to a string with a binar representation of the number
std::string convertDecimalStringToBinaryString(std::string& str)
{
// Resulting string
std::string binaryDigits{};
// Until the string is empty. Will be shorter and short because of devision by 2
while (!str.empty()) {
// For an even number we add 0, for an odd number we add 1
binaryDigits += (oddNumbers.find(str.back()) == std::string::npos) ? '0' : '1';
// And devide by 2
divideDecimalNumberAsStringBy2(str);
}
// Bits come in wrong order, so we need to revers it
std::reverse(binaryDigits.begin(), binaryDigits.end());
return binaryDigits;
}
int main()
{
// Initial string with a big number. Get input from user
std::string bigNumber{};
std::cout << "Enter big number: ";
std::cin >> bigNumber;
// Convert it
std::string binaryDigits = convertDecimalStringToBinaryString(bigNumber);
// Find the last 0
unsigned int posOfLast0 = binaryDigits.rfind('0');
// Show result
if (posOfLast0 == std::string::npos)
std::cout << "\nNo digit is 0 --> " << binaryDigits << '\n';
else
std::cout << "\nSize of resulting string: "<< binaryDigits.size() << "\nPos of last 0: " << posOfLast0+1 << "\nBinary String:\n\n" << binaryDigits << '\n';
return 0;
}
Related
I want to reverse the array, The code works normally if I give it a input without any blank space but it doesn't work if there is a blank space in it.
e.g. instead of 1234, I give 1 2 3 4 and it would generate incorrect answer.
I tried using conversions from int to string to use getline() to get rid of blank space but that didn't work.
here is my code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string n, y; // string var declared
int z, rev=0, rem; // int var declared
getline(cin,n); // taken input as sting n
z = stoi(n); // converting sting n to int and storing in z
int *arr = new int(z); // setting z as dynamic array of integers
for (int x=0; x<=z; x++) { // running a loop till x <= z
y = to_string(x); // converting integer x into a string y
cin >> y; // taking inputs as string y
x = stoi(y); // converting string y to integer x
// logic
while(x!=0) { // while int x != 0 run loop
rem=x%10; // finding remainder
rev=rev*10+rem; // adding remainder to var rev i.e reverse
x/=10; // rounding off to remaining numbers
} // closing loop of while
cout<<rev; // printing the final reversed number
} //closing for loop
return 0;
} //closing int main
If you want to process only digits then get rid of everything else with this piece:
getline(cin,n);
std::string inp;
for(auto &s : n)
if (std::isdigit(s)) inp.push_back(s);
Then use inp, it will be free of any non digit characters.
If want to process these digits as independent numbers, you can do this:
std::vector<int> num_inp;
for (auto &s : n)
if (std::isdigit(s))
num_inp.push_back(std::stoi(s));
each digit will be its own number in std::vector.
There are so many possible answers that it is difficult to answer. Either you may use all build in C++ algorithms or, you want a handcrafted solution.
It depends also little bit, if you want to validate the input and allow only digits and spaces or, if you just want to ignore whitespace.
In any case, reading a complete line with std::getline and then do the validation or ignore the spaces or whatever, is the preferred solution.
If you have read the input into str, then you may validate it with a std::regex_match. Or, you can iterate over the string and can check charachter by character.
Ignoring or eliminating the space can be done with std::regex_replace or by putting the std::string into an istringstream and use standard io functions to extract the numbers from there. Using formated input will skip white space.
This is problematic while reading directly from std::cin because finding the and-of-line is -very astonishing- notoriously difficult.
See the following somehow clumsy example:
#include <iostream>
int main() {
unsigned long numberToReverse{};
unsigned long numberTemp{};
// Read as many number parts as existing, even devided by space
while (std::cin >> numberTemp) {
// We need to shift the previous read numbers to the left
// This we do by multiplications of 10. For as many digits as we have in the new part
unsigned long temp{ numberTemp };
do {
numberToReverse *= 10;
} while (temp /= 10);
// Now add the new digits to the right end
numberToReverse += numberTemp;
// In case of '\n', so 'end of line' stop
if (std::cin.peek() == '\n') break;
}
// Reverse digits
unsigned long outputNumber{}; // For output
while(numberToReverse) {
outputNumber *= 10; // Shift digits in output 1 position left
outputNumber += numberToReverse % 10; // Get next digit from input
numberToReverse /= 10; // Look at next digit to the left of the input
}
// Show result
std::cout << outputNumber << '\n';
return 0;
}
OK, it does use only standard iosstream facilities, but it uses peek and will only work, if there is a number directly followed by an '\n' at the end of the input. So, not very good.
Then we may switch to the preferred solution and reada complete line as a string. Put that string into an std::istringstream and extract from there.
#include <iostream>
#include <string>
#include <sstream>
int main() {
unsigned long numberToReverse{};
// Read whateverinput to a string
if (std::string inputAsString{}; std::getline(std::cin, inputAsString)) {
// Put the string into a stringstream toextract the integers
std::istringstream inputAsStringstream{ inputAsString };
// Extract all numbers
unsigned long numberTemp{};
while (inputAsStringstream >> numberTemp) {
// We need to shift the previous read numbers to the left
// This we do by multiplications of 10. For as many digits as we have in the new part
unsigned long temp{ numberTemp };
do {
numberToReverse *= 10;
} while (temp /= 10);
// Now add the new digits to the right end
numberToReverse += numberTemp;
}
}
// Reverse digits
unsigned long outputNumber{}; // For output
while (numberToReverse) {
outputNumber *= 10; // Shift digits in output 1 position left
outputNumber += numberToReverse % 10; // Get next digit from input
numberToReverse /= 10; // Look at next digit to the left of the input
}
// Show result
std::cout << outputNumber << '\n';
return 0;
}
Please note: There is no need to use an array. You can directly calculate each digit by interger and modulo division. And to determin the correct position, we can shift the digits to the left, by multiplication with 10.
These are standard methods and may be found here on SO many times.
And last but not least, the more modern C++ solution, ourely working with strings.
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
int main() {
// Read string
if (std::string inputAsString{}; std::getline(std::cin, inputAsString))
// Show reversed output
std::copy(inputAsString.crbegin(), inputAsString.crend(), std::ostream_iterator<char>(std::cout));
return 0;
}
You may of course use some validation mechanism after reading the string from std::cin
I Learnt about vectors to resolve this problem, hope this is helpful to someone who might have similar problem in the future.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void display(vector<int> &v)
{
reverse(v.begin(), v.end());
for(int i=0; i < v.size(); i++)
{
cout<<v[i]<<" ";
}
}
int main()
{
vector<int> n;
int size, element;
cout<<"enter the number of elements you want reversed ";
cin>>size;
for(int i=1; i<=size; ++i)
{
//cout<<"Enter elements to be reversed ";
cin>>element;
n.push_back(element);
}
display(n);
return 0;
}
``
Please help me to identify the error in this program, as for me it's looking correct,I have checked it,but it is giving wrong answers.
In this program I have checked explicitly for A,B,C,D,E,F,and according to them their respective values.
[Edited]:Also,this question relates to how a character number is converted to actual integer number.
#include<iostream>
#include<cmath>
#include<bits/stdc++.h>
using namespace std;
void convert(string num)
{
long int last_digit;
int s=num.length();
int i;
long long int result=0;
reverse(num.begin(),num.end());
for(i=0;i<s;i++)
{
if(num[i]=='a' || num[i]=='A')
{
last_digit=10;
result+=last_digit*pow(16,i);
}
else if(num[i]=='b'|| num[i]=='B')
{
last_digit=11;
result+=last_digit*pow(16,i);
}
else if(num[i]=='c' || num[i]=='C')
{
last_digit=12;
result+=last_digit*pow(16,i);
}
else if(num[i]=='d'|| num[i]=='D' )
{
last_digit=13;
result+=last_digit*pow(16,i);
}
else if(num[i]=='e'|| num[i]=='E' )
{
last_digit=14;
result+=last_digit*pow(16,i);
}
else if(num[i]=='f' || num[i]=='F')
{
last_digit=15;
result+=last_digit*pow(16,i);
}
else {
last_digit=num[i];
result+=last_digit*pow(16,i);
}
}
cout<<result;
}
int main()
{
string hexa;
cout<<"Enter the hexadecimal number:";
getline(cin,hexa);
convert(hexa);
}
Your code is very convoluted and wrong.
You probably want this:
void int convert(string num)
{
long int last_digit;
int s = num.length();
int i;
long long int result = 0;
for (i = 0; i < s; i++)
{
result <<= 4; // multiply by 16, using pow is overkill
auto digit = toupper(num[i]); // convert to upper case
if (digit >= 'A' && digit <= 'F')
last_digit = digit - 'A' + 10; // digit is in range 'A'..'F'
else
last_digit = digit - '0'; // digit is (hopefully) in range '0'..'9'
result += last_digit;
}
cout << result;
}
But this is still not very good:
the function should return a long long int instead of printing the result
a few other thing can be done mor elegantly
So a better version would be this:
#include <iostream>
#include <string>
using namespace std;
long long int convert(const string & num) // always pass objects as const & if possible
{
long long int result = 0;
for (const auto & ch : num) // use range based for loops whenever possible
{
result <<= 4;
auto digit = toupper(ch);
long int last_digit; // declare local variables in the inner most scope
if (digit >= 'A' && digit <= 'F')
last_digit = digit - 'A' + 10;
else
last_digit = digit - '0';
result += last_digit;
}
return result;
}
int main()
{
string hexa;
cout << "Enter the hexadecimal number:";
getline(cin, hexa);
cout << convert(hexa);
}
There is still room for more improvements as the code above assumes that the string to convert contains only hexadecimal characters. Ideally a check for invalid characters should be done somehow. I leave this as an exercise.
The line last_digit = digit - 'A' + 10; assumes that the codes for letters A to F are contiguous, which in theory might not be the case. But the probability that you'll ever encounter an encoding scheme where this is not the case is close to zero though. The vast majority of computer systems in use today use the ASCII encoding scheme, some use EBCDIC, but in both of these encoding schemes the character codes for letters A to F are contiguous. I'm not aware of any other encoding scheme in use today.
Your problem is in the elsecase in which you convert num[i] from char to its ascii equivalent. Thus, for instance, if you try to convert A0, the 0is converted into 48 but not 0.
To correct, you should instead convert your num[i] into its equivalent integer (not in asci).
To do so, replace :
else {
last_digit=num[i];
result+=last_digit*pow(16,i);
with
else {
last_digit = num[i]-'0';
result+=last_digit*pow(16,i);
}
In the new line, last_digit = num[i]-'0'; is equivalent to last_digit = (int)num[i]-(int)'0';which substracts the representation code of any one-digit-number from num[i] from the representation code of '0'
It works because the C++ standard guarantee that the number representation of the 10 decimal digits are contiguous and in incresing order (official ref iso-cpp and is stated in chapter 2.3 and paragraph 3
Thus, if you take the representation (for instance the ascii code) of any one-digit-number num[i] and substract it with the representation code of '0' (which is 48 in ascii), you obtain directly the number itself as an integer value.
An example of execution after the correction would give:
A0
160
F5
245
A small codereview:
You are repeating yourself with many result+=last_digit*pow(16,i);. you may do it only once at the end of the loop. But that's another matter.
You are complicating the problem more than you need to (std::pow is also kinda slow). std::stoul can take a numerical base and automatically convert to an integer for you:
#include <string>
#include <iostream>
std::size_t char_count{0u};
std::string hexa{};
std::getline(std::cin, hexa);
hexa = "0x" + hexa;
unsigned long value_uint = std::stoul(hexa, &char_count, 16);
The Problem:
A company is distributing phone numbers to its employees to make things easier. the next digit cannot be equal to the last is the only rule for example 0223 is not allowed while 2023 is allowed. At least three digits will be excluded every time. Write a function that takes in a length of the phone number and the digits that will be excluded. The function should print all possible phone numbers.
I got this question in an interview and I have seen one like it before at my university. It is a permutation problem. My question is what is the best way or decent way to solve this without a million for loops.
I do understand that this is technically how it works
length of phone number = 3;
[0-9], [0-9] excluding the last digit, [0-9] excluding the last digit
but I am unsure on how the best way to turn this into code. Any language is accepted!
thank you:
Also I might be asking this in the wrong place. please let me know if I am.
A simple way to solve this problem could be using Recursion. Here's my commented C++ code:
void solve(int depth, int size, vector <int> &curr_seq){
// If the recursion depth is equal to size, that means we've decided size
// numbers, which means that curr_seq.size() == size. In other words, we've
// decided enough numbers at this point to create a complete phone number, so
// we print it and return.
if(depth == size){
for(int item : curr_seq){
cout << item;
}
cout << "\n";
return;
}
// Try appending every possible digit to the current phone number
for(int i = 0; i <= 9; ++i){
// Make sure to only append the digit i if it is not equal to the last digit
// of the phone number. We can also append it, however, if curr_seq
// is empty (because that means that we haven't decided the 1st digit yet).
if(curr_seq.empty() || curr[curr.size() - 1] != i){
curr_seq.push_back(i);
solve(depth + 1, size, curr);
curr_seq.pop_back();
}
}
}
I think I like the recursive solution, but you can also just generate all permutations up to the limit (iterate), filter out any with repeating digits, and print the successful candidates:
#include <iomanip>
#include <iostream>
#include <sstream>
using namespace std;
// Because C/C++ still has no integer power function.
int ipow(int base, int exp) {
int result = 1;
for (;;) {
if (exp & 1)
result *= base;
exp >>= 1;
if (!exp)
return result;
base *= base;
}
}
void noconsec(const int len) {
int lim = ipow(10, len);
// For e.g. len 4 (lim 10000),
// obviously 00xx won't work, so skip anything smaller than lim / 100.
int start = (len <= 2) ? 0 : (lim / 100);
for (int num = start;num < lim;num++) {
// Convert to string.
std::stringstream ss;
ss << std::setw(len) << std::setfill('0') << num;
std::string num_s = ss.str();
// Skip any consecutive digits.
bool is_okay = true;
auto prev_digit = num_s[0];
for (int digit_idx = 1;digit_idx < num_s.length();digit_idx++) {
auto digit = num_s[digit_idx];
if (prev_digit == digit) {
is_okay = false;
}
prev_digit = digit;
}
// Output result.
if (is_okay) {
cout << num_s << "\n";
}
}
}
int main(const int argc, const char * const argv[]) {
noconsec(4);
}
Differences to note, this needs an integer power function to compute the limit. Converting an int to a string and then checking the string is more complex than constructing the string directly. I guess it could be useful if you have a list of integers already, but mostly I did it for fun.
For example:
string binaryValue = "11111111111111111111111111111011" // -5
I need to convert this string to decimal representatin of this number.
stoi(binaryValue, nullptr, 2)
Will throw exception on this case. So how can i do this in c++ ? String or int doesn't matter.
See the documentation of:
int std::stoi( const std::string& str, std::size_t* pos = 0, int base = 10 );
in particular:
The valid integer value [of str] consists of the following parts:
(optional) plus or minus sign
...
...
If the minus sign was part of the input sequence, the numeric value calculated
from the sequence of digits is negated as if by unary minus in the result type.
Exceptions
std::invalid_argument if no conversion could be performed
std::out_of_range if the converted value would fall out of the range of
the result type...
In the absence of a preceding minus-sign, the string:
std::string binaryValue = "11111111111111111111111111111011";
will be interpreted in a the call:
std::stoi(binaryValue, nullptr, 2);
as a non-negative integer value in base-2 representation. But as such,
it is out of range, so std::out_of_range is thrown:
To represent -5 as a string that your std::stoi call will convert as you expect,
use:
std::string const binaryValue = "-101";
Live demo
If you don't want to prefix a minus sign to a non-negative base-2 numeral, or cannot do so in your real-world
situation, but wish to interpret "11111111111111111111111111111011"
as the two's complement representation of a signed integer using the std::sto* API,
then you must first convert the string to an unsigned integer of a wide-enough
type, and then convert that unsigned value to a signed one. E.g.
#include <string>
#include <iostream>
int main()
{
auto ul = std::stoul("11111111111111111111111111111011",nullptr,2);
std::cout << ul << std::endl;
int i = ul;
std::cout << i << std::endl;
return 0;
}
Live demo
as you probably know number are stored as Twos Complement
to convert it using simple pseudocode
flip numbers 0->1, 1->0 from left to write util you find last 1 in string don't toggle this one
this will be your answer
0000000000000000000000000101=5
here is the code brouht from https://www.geeksforgeeks.org/efficient-method-2s-complement-binary-string/
#include<bits/stdc++.h>
using namespace std;
string findTwoscomplement(string str)
{
int n = str.length();
// Traverse the string to get first '1' from
// the last of string
int i;
for (i = n ; i >= 0 ; i--)
if (str[i] == '1')
break;
// If there exists no '1' concat 1 at the
// starting of string
if (i == 0)
return '1' + str;
// Continue traversal after the position of
// first '1'
for (int k = i-1 ; k >= 0; k--)
{
//Just flip the values
if (str[k] == '1')
str[k] = '0';
else
str[k] = '1';
}
// return the modified string
return str;;
}
int main()
{
string str = "11111111111111111111111111111011";
cout << findTwoscomplement(str);
//now you convert it to decimal if you want
cout<<"Hello World";
cout << stoul( findTwoscomplement(str),nullptr,2);
return 0;
}
preview at https://onlinegdb.com/SyFYLVtdf
I am currently working on a basic program which converts a binary number to an octal. Its task is to print a table with all the numbers between 0-256, with their binary, octal and hexadecimal equivalent. The task requires me only to use my own code (i.e. using loops etc and not in-built functions). The code I have made (it is quite messy at the moment) is as following (this is only a snippit):
int counter = ceil(log10(fabs(binaryValue)+1));
int iter;
if (counter%3 == 0)
{
iter = counter/3;
}
else if (counter%3 != 0)
{
iter = ceil((counter/3));
}
c = binaryValue;
for (int h = 0; h < iter; h++)
{
tempOctal = c%1000;
c /= 1000;
int count = ceil(log10(fabs(tempOctal)+1));
for (int counter = 0; counter < count; counter++)
{
if (tempOctal%10 != 0)
{
e = pow(2.0, counter);
tempDecimal += e;
}
tempOctal /= 10;
}
octalValue += (tempDecimal * pow(10.0, h));
}
The output is completely wrong. When for example the binary code is 1111 (decimal value 15), it outputs 7. I can understand why this happens (the last three digits in the binary number, 111, is 7 in decimal format), but can't be able to identify the problem in the code. Any ideas?
Edit: After some debugging and testing I figured the answer.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
while (true)
{
int binaryValue, c, tempOctal, tempDecimal, octalValue = 0, e;
cout << "Enter a binary number to convert to octal: ";
cin >> binaryValue;
int counter = ceil(log10(binaryValue+1));
cout << "Counter " << counter << endl;
int iter;
if (counter%3 == 0)
{
iter = counter/3;
}
else if (counter%3 != 0)
{
iter = (counter/3)+1;
}
cout << "Iterations " << iter << endl;
c = binaryValue;
cout << "C " << c << endl;
for (int h = 0; h < iter; h++)
{
tempOctal = c%1000;
cout << "3 digit binary part " << tempOctal << endl;
int count = ceil(log10(tempOctal+1));
cout << "Digits " << count << endl;
tempDecimal = 0;
for (int counterr = 0; counterr < count; counterr++)
{
if (tempOctal%10 != 0)
{
e = pow(2.0, counterr);
tempDecimal += e;
cout << "Temp Decimal value 0-7 " << tempDecimal << endl;
}
tempOctal /= 10;
}
octalValue += (tempDecimal * pow(10.0, h));
cout << "Octal Value " << octalValue << endl;
c /= 1000;
}
cout << "Final Octal Value: " << octalValue << endl;
}
system("pause");
return 0;
}
This looks overly complex. There's no need to involve floating-point math, and it can very probably introduce problems.
Of course, the obvious solution is to use a pre-existing function to do this (like { char buf[32]; snprintf(buf, sizeof buf, "%o", binaryValue); } and be done, but if you really want to do it "by hand", you should look into using bit-operations:
Use binaryValue & 3 to mask out the three lowest bits. These will be your next octal digit (three bits is 0..7, which is one octal digit).
use binaryValue >>= 3 to shift the number to get three new bits into the lowest position
Reverse the number afterwards, or (if possible) start from the end of the string buffer and emit digits backwards
It don't understand your code; it seems far too complicated. But one
thing is sure, if you are converting an internal representation into
octal, you're going to have to divide by 8 somewhere, and do a % 8
somewhere. And I don't see them. On the other hand, I see a both
operations with both 10 and 1000, neither of which should be present.
For starters, you might want to write a simple function which converts
a value (preferably an unsigned of some type—get unsigned
right before worrying about the sign) to a string using any base, e.g.:
//! \pre
//! base >= 2 && base < 36
//!
//! Digits are 0-9, then A-Z.
std::string convert(unsigned value, unsigned base);
This shouldn't take more than about 5 or 6 lines of code. But attention,
the normal algorithm generates the digits in reverse order: if you're
using std::string, the simplest solution is to push_back each digit,
then call std::reverse at the end, before returning it. Otherwise: a
C style char[] works well, provided that you make it large enough.
(sizeof(unsigned) * CHAR_BITS + 2 is more than enough, even for
signed, and even with a '\0' at the end, which you won't need if you
return a string.) Just initialize the pointer to buffer +
sizeof(buffer), and pre-decrement each time you insert a digit. To
construct the string you return:
std::string( pointer, buffer + sizeof(buffer) ) should do the trick.
As for the loop, the end condition could simply be value == 0.
(You'll be dividing value by base each time through, so you're
guaranteed to reach this condition.) If you use a do ... while,
rather than just a while, you're also guaranteed at least one digit in
the output.
(It would have been a lot easier for me to just post the code, but since
this is obviously homework, I think it better to just give indications
concerning what needs to be done.)
Edit: I've added my implementation, and some comments on your new
code:
First for the comments: there's a very misleading prompt: "Enter a
binary number" sounds like the user should enter binary; if you're
reading into an int, the value input should be decimal. And there are
still the % 1000 and / 1000 and % 10 and / 10 that I don't
understand. Whatever you're doing, it can't be right if there's no %
8 and / 8. Try it: input "128", for example, and see what you get.
If you're trying to input binary, then you really have to input a
string, and parse it yourself.
My code for the conversion itself would be:
//! \pre
//! base >= 2 && base <= 36
//!
//! Digits are 0-9, then A-Z.
std::string toString( unsigned value, unsigned base )
{
assert( base >= 2 && base <= 36 );
static char const digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer[sizeof(unsigned) * CHAR_BIT];
char* dst = buffer + sizeof(buffer);
do
{
*--dst = digits[value % base];
value /= base;
} while (value != 0);
return std::string(dst, buffer + sizeof(buffer));
}
If you want to parse input (e.g. for binary), then something like the
following should do the trick:
unsigned fromString( std::string const& value, unsigned base )
{
assert( base >= 2 && base <= 36 );
static char const digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned results = 0;
for (std::string::const_iterator iter = value.begin();
iter != value.end();
++ iter)
{
unsigned digit = std::find
( digits, digits + sizeof(digits) - 1,
toupper(static_cast<unsigned char>( *iter ) ) ) - digits;
if ( digit >= base )
throw std::runtime_error( "Illegal character" );
if ( results >= UINT_MAX / base
&& (results > UINT_MAX / base || digit > UINT_MAX % base) )
throw std::runtime_error( "Overflow" );
results = base * results + digit;
}
return results;
}
It's more complicated than toString because it has to handle all sorts
of possible error conditions. It's also still probably simpler than you
need; you probably want to trim blanks, etc., as well (or even ignore
them: entering 01000000 is more error prone than 0100 0000).
(Also, the end iterator for find has a - 1 because of the trailing
'\0' the compiler inserts into digits.)
Actually I don't understand why do you need so complex code to accomplish what you need.
First of all there is no such a thing as conversion from binary to octal (same is true for converting to/from decimal and etc.). The machine always works in binary, there's nothing you can (or should) do about this.
This is actually a question of formatting. That is, how do you print a number as octal, and how do you parse the textual representation of the octal number.
Edit:
You may use the following code for printing a number in any base:
const int PRINT_NUM_TXT_MAX = 33; // worst-case for binary
void PrintNumberInBase(unsigned int val, int base, PSTR szBuf)
{
// calculate the number of digits
int digits = 0;
for (unsigned int x = val; x; digits++)
x /= base;
if (digits < 1)
digits = 1; // will emit zero
// Print the value from right to left
szBuf[digits] = 0; // zero-term
while (digits--)
{
int dig = val % base;
val /= base;
char ch = (dig <= 9) ?
('0' + dig) :
('a' + dig - 0xa);
szBuf[digits] = ch;
}
}
Example:
char sz[PRINT_NUM_TXT_MAX];
PrintNumberInBase(19, 8, sz);
The code the OP is asking to produce is what your scientific calculator would do when you want a number in a different base.
I think your algorithm is wrong. Just looking over it, I see a function that is squared towards the end. why? There is a simple mathematical way to do what you are talking about. Once you get the math part, then you can convert it to code.
If you had pencil and paper, and no calculator (similar to not using pre built functions), the method is to take the base you are in, change it to base 10, then change to the base you require. In your case that would be base 8, to base 10, to base 2.
This should get you started. All you really need are if/else statements with modulus to get the remainders.
http://www.purplemath.com/modules/numbbase3.htm
Then you have to figure out how to get your desired output. Maybe store the remainders in an array or output to a txt file.
(For problems like this is the reason why I want to double major with applied math)
Since you want conversion from decimal 0-256, it would be easiest to make functions, say call them int binary(), char hex(), and int octal(). Do the binary and octal first as that would be the easiest since they can represented by only integers.
#include <cmath>
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
#include <cstdlib>
using namespace std;
char* toBinary(char* doubleDigit)
{
int digit = atoi(doubleDigit);
char* binary = new char();
int x = 0 ;
binary[x]='(';
//int tempDigit = digit;
int k=1;
for(int i = 9 ; digit != 0; i--)
{
k=1;//cout << digit << endl;
//cout << "i"<< i<<endl;
if(digit-k *pow(8,i)>=0)
{
k =1;
cout << "i" << i << endl;
cout << k*pow(8,i)<< endl;
while((k*pow(8,i)<=digit))
{
//cout << k <<endl;
k++;
}
k= k-1;
digit = digit -k*pow(8,i);
binary[x+1]= k+'0';
binary[x+2]= '*';
binary[x+3]= '8';
binary[x+4]='^';
binary[x+5]=i+'0';
binary[x+6]='+';
x+=6;
}
}
binary[x]=')';
return binary;
}
int main()
{
char value[6]={'4','0','9','8','7','9'};
cout<< toBinary(value);
return 0 ;
}