Project Euler 8 in c++ - c++

I'm trying to solve problem 8 from project euler but I'm getting way too big numbers as results and I don't know why.
The problem is "Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?"
My code :
#include <iostream>
#include <string>
int main()
{
std::string str = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
long long a = 1;
long long fin = 0;
for (int c = 0; c < 988; c++)
{
for (int d = 0; d < 13; d++)
{
a = a * str.at(c + d);
}
if (a > fin)
{
fin = a;
std::cout << fin << " at " << c << std::endl;
}
a = 1;
}
system("pause");
}
The output :
7948587103611909356 at 0
8818137127266647872 at 15
8977826317031653376 at 71
9191378290313403392 at 214
9205903071867879424 at 573
Press any key to continue...

The problem is that the characters '0' through '9' are not the same as the integers 0 through 9; rather, '0' has the value 48, '1' has the value 49, and so on. (These are the ASCII values of those characters.)
So to convert from a digit character to the desired number — for example, to extract e.g. 3 from '3' — you need to subtract '0'. In other words, you need to change this:
a = a * str.at(c + d);
to this:
a = a * (str.at(c + d) - '0');

Related

Code to convert decimal to hexadecimal without using arrays

I have this code here and I'm trying to do decimal to hexadecimal conversion without using arrays. It is working pretty much but it gives me wrong answers for values greater than 1000. What am I doing wrong? are there any counter solutions? kindly can anyone give suggestions how to improve this code.
for(int i = num; i > 0; i = i/16)
{
temp = i % 16;
(temp < 10) ? temp = temp + 48 : temp = temp + 55;
num = num * 100 + temp;
}
cout<<"Hexadecimal = ";
for(int j = num; j > 0; j = j/100)
{
ch = j % 100;
cout << ch;
}
There's a couple of errors in the code. But elements of the approach are clear.
This line sort of works:
(temp < 10) ? temp = temp + 48 : temp = temp + 55;
But is confusing because it's using 48 and 55 as magic numbers!
It also may lead to overflow.
It's repacking hex digits as decimal character values.
It's also unconventional to use ?: in that way.
Half the trick of radix output is that each digit is n%r followed by n/r but the digits come out 'backwards' for conventional left-right output.
This code reverses the hex digits into another variable then reads them out.
So it avoids any overflow risks.
It works with an unsigned value for clarity and a lack of any specification as how to handle negative values.
#include <iostream>
void hex(unsigned num){
unsigned val=num;
const unsigned radix=16;
unsigned temp=0;
while(val!=0){
temp=temp*radix+val%radix;
val/=radix;
}
do{
unsigned digit=temp%16;
char c=digit<10?'0'+digit:'A'+(digit-10);
std::cout << c;
temp/=16;
}while(temp!=0);
std::cout << '\n';
}
int main(void) {
hex(0x23U);
hex(0x0U);
hex(0x7U);
hex(0xABCDU);
return 0;
}
Expected Output:
23
0
8
ABCD
Arguably it's more obvious what is going on if the middle lines of the first loop are:
while(val!=0){
temp=(temp<<4)+(val&0b1111);
val=val>>4;
}
That exposes that we're building temp as blocks of 4 bits of val in reverse order.
So the value 0x89AB with be 0xBA98 and is then output in reverse.
I've not done that because bitwise operations may not be familiar.
It's a double reverse!
The mapping into characters is done at output to avoid overflow issues.
Using character literals like 0 instead of integer literals like 44 is more readable and makes the intention clearer.
So here's a single loop version of the solution to the problem which should work for any sized integer:-
#include <iostream>
#include <string>
using namespace std;
void main(int argc, char *argv[1])
{
try
{
unsigned
value = argc == 2 ? stoi(argv[1]) : 64;
for (unsigned i = numeric_limits<unsigned>::digits; i > 0; i -= 4)
{
unsigned
digit = (value >> (i - 4)) & 0xf;
cout << (char)((digit < 10) ? digit + 48 : digit + 55);
}
cout << endl;
}
catch (exception e)
{
cout << e.what() << endl;
}
}
There is a mistake in your code, in the second loop you should exit when j > original num, or set the cumulative sum with non-zero value, I also changed the cumulative num to be long int, rest should be fine.
void tohex(int value){
long int num = 1;
char ch = 0;
int temp = 0;
for(int i = value; i > 0; i = i/16)
{
temp = i % 16;
(temp < 10) ? temp = temp + 48 : temp = temp + 55;
num = num * 100 + temp;
}
cout<<"Hexadecimal = ";
for(long int j = num; j > 99; j = j/100)
{
ch = j % 100;
cout << ch;
}
cout << endl;
}
If this is a homework assignment, it is probably related to the chapter on Recursivity. See a solution below. To understand it, you need to know
what a lookup table is
what recursion is
how to convert a number from one base to another iteratively
basic io
void hex_out(unsigned n)
{
static const char* t = "0123456789abcdef"; // lookup table
if (!n) // recursion break condition
return;
hex_out(n / 16);
std::cout << t[n % 16];
}
Note that there is no output for zero. This can be solved simply by calling the recursive function from a second function.
You can also add a second parameter, base, so that you can call the function this way:
b_out(123, 10); // decimal
b_out(123, 2); // binary
b_out(123, 8); // octal

Cipher Algorithm Problems

Task: This cipher shifts each letter by a number of letters. If the shift takes you past the end of the alphabet, just rotate back to the front of the alphabet.
For example:
string = "Abc Def Ghi 999 -*%/&()[]"
shift(number that you entered) = 1(Can be any integer)
Program should print like this: Bcd Efg Hij -*%/&()[]
I did this with a void function but once I tried to do same thing with string function it didn't work. It just process first element of string then returns the value. For this particular situation
my program prints like "Bbc Def Ghi 999 -*%/&()[]"
Any idea to solve this problem?
#include <iostream>
#include <cmath>
using namespace std;
string Cipher(string password, int shift) {
char Uppercase[26] = { 'A','B','C' ,'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O','P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y','Z' };
char Lowercase[26] = { 'a','b','c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o','p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' ,'y','z' };
for (int i = 0; i < password.length(); i++) {
for (int k = 0; k < 26; k++) {
int add = shift + k;
if (password[i] == Uppercase[k]) {
for (int i = 0; add > 25; i++) { // controlling add isn't bigger than 25
add -= 25;
}
password[i] = Uppercase[add]; // converting each letter
}
else if (password[i] == Lowercase[k]) {
for (int i = 0; add > 25; i++) { // controlling add isn't bigger than 25
add -= 25;
}
password[i] = Lowercase[add]; //converting each letter
}
else {
k = 25; // if element of string is different from letters, program goes to next element
}
}
}
return password;
}
int main() {
cout << "Please enter an integer different from 0 and multiples of 25: ";
string password = "Abc def ghi 999 -*%/&()[]";
int shift;
cin >> shift;
cout<< Cipher(password, shift);
system("pause>0");
}
Your encryption problem can be solved with one statement by using modern C++.
But because this is somehow advanced, I will give a detailed explanation.
Let us first think, what to do and then, how to implement.
The what:
Only alpha characters shall be converted
None alpha characters shall be output unencrypted (same as input)
In case of encryption, the case of the original letter shall be preserved for the encrypted letter. Meaning, if at position 5 was an uppcase letter, also in the encrypted string the letter in position 5 shall be uppercase
Letters shall be shifted by a specified amount.
The how:
We will first check, it the original letter is an alpha-letter by using the isalpha-function.
So, for the case that it is an alpha letter, we will check, if the letter is in uppercase or in lowercase. Actually, we check only, if it is a uppercase letter.
Because if it is not, then it must be a lowercase letter (because it was definitely a letter, what we did check before, and, if it is not upper, then it is lower case). For this check, we use the isupper-function.
We will then do the shift action. And convert back to a letter, taken the case into account.
We assume ASCII. If we to convert an ASCII letter/character into a 0 based index, we need to do the following:
If we look in the ASCII table, then we see, that and 'A' is equivalent to 65 and so forth. So, to get the 0-based index, we subtract 65 from the letter. Then we have an index value between 0 and 25.
Then we add the shift value. There could of course be an overflow. But, this can be simply corrected by a modulo 26 division.
So: 26->0, 27->1, 28->2 and so on. Rather simple. But, because we want to have later a letter again, we will add 65 to this result.
For lowercase letters, we will do nearly the same, but use 97 for the offset to letter 'a'.
Then, we can put verything in one expresion by using the ternary or conditional-operator.
std::isalpha(c) ? std::isupper(c) ? (c - 65 + shift) % 26 + 65 : (c - 97 + shift) % 26 + 97 : c
This is a short for
// Check if letter/character is alpha
if (std::isalpha(c)) {
// Now check for upper or lower case
if (std::isupper(c)) {
// The character is uppercase
c = (c - 65 + shift) % 26 + 65;
}
else {
// The character is lower case
c = (c - 97 + shift) % 26 + 97;
}
}
else {
// The character is not alpha
}
Same as the one liner, no difference
So, first, check for alpha. If true, check for uppercase, if true, do the conversion for uppcase letter, else for lower case letters. If it was no alpha letter, then leave it unchanged.
All this we will then embed as a Lambda-expresion in a std::transform-statement. Please see here for a description.
The result will be one statement only, for the whole conversion process:
std::transform(password.begin(), password.end(), password.begin(), [shift](const char c)
{return std::isalpha(c) ? std::isupper(c) ? (c - 65 + shift) % 26 + 65 : (c - 97 + shift) % 26 + 97 : c; });
At the end, we build a small driver program for demo purposes:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
// Our password
std::string password = "Abc def ghi 999 -*%/&()[]";
// Give instruction to the user
std::cout << "\nPlease enter a postive integer: ";
// Get number of shifts from user and check, if the value could be read
if (int shift{}; std::cin >> shift && shift > 0) {
// Now do the encryption
std::transform(password.begin(), password.end(), password.begin(), [shift](const char c)
{return std::isalpha(c) ? std::isupper(c) ? (c - 65 + shift) % 26 + 65 : (c - 97 + shift) % 26 + 97 : c; });
// Show the result to the user
std::cout << "\n\nEncrypted passphrase: \t" << password << '\n';
}
else std::cerr << "\n\n*** Error: Problem with input!\n\n";
return 0;
}
And, since the one liner is maybe too advanced, let's use the explicit and more verbose code. Just to be complete:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
// Our password
std::string password = "Abc def ghi 999 -*%/&()[]";
// Give instruction to the user
std::cout << "\nPlease enter a postive integer: ";
// Get number of shifts from user and check, if the value could be read
if (int shift{}; std::cin >> shift && shift > 0) {
// --------------Can be written in one statement -----------------------
for (char& c : password) {
// Check if letter/character is alpha
if (std::isalpha(c)) {
// Now check for upper or lower case
if (std::isupper(c)) {
// The character is uppercase
c = (c - 65 + shift) % 26 + 65;
}
else {
// The character is lower case
c = (c - 97 + shift) % 26 + 97;
}
}
else {
// The character is not alpha
}
// ------------------------------------------------------------------
}
// Show the result to the user
std::cout << "\n\nEncrypted passphrase: \t" << password << '\n';
}
else std::cerr << "\n\n*** Error: Problem with input!\n\n";
return 0;
}
Within your k loop you determine the index of the letter in the alphabet. However, when e.g. i=1 then password[1] represents the letter 'b'. Now, starting the k-loop from k==0 where Uppercase[0] and Lowercase[0] represent 'A' and 'a', respectively, you directly end up in the else condition and your k-loop terminates without doing anything (you set k=25 and increment it). Here is a fixed version (note that I also use the modulo operator % to make sure that 0 < add < 26:
#include <iostream>
#include <cmath>
using namespace std;
string Cipher(string password, int shift) {
char Uppercase[26] = { 'A','B','C' ,'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O','P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y','Z' };
char Lowercase[26] = { 'a','b','c' ,'d' ,'e' ,'f' ,'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o','p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,'x' ,'y','z' };
for (int i = 0; i < password.length(); i++) {
for (int k = 0; k < 26; k++) {
int add = (shift + k)%26;
if (password[i] == Uppercase[k]) {
password[i] = Uppercase[add]; // converting each letter
break;
}
else if (password[i] == Lowercase[k]) {
password[i] = Lowercase[add]; //converting each letter
break;
}
}
}
return password;
}
int main() {
cout << "Please enter an integer different from 0 and multiples of 25: ";
string password = "Abc def ghi 999 -*%/&()[]";
int shift;
cin >> shift;
cout<< Cipher(password, shift);
system("pause>0");
}

Convert a 74-bit integer to base 31

To generate a UFI number, I use a bitset of size 74. To perform step 2 of UFI generation, I need to convert this number:
9 444 732 987 799 592 368 290
(10000000000000000000000000000101000001000001010000011101011111100010100010)
into:
DFSTTM62QN6DTV1
by converting the first representation to base 31 and getting the equivalent chars from a table.
#define PAYLOAD_SIZE 74
// payload = binary of 9444732987799592368290
std::bitset<PAYLOAD_SIZE> bs_payload(payload);
/*
perform modulo 31 to obtain:
12(D), 14(F), 24(S), 25(T), 25, 19, 6, 2, 22, 20, 6, 12, 25, 27, 1
*/
Is there a way to perform the conversion on my bitset without using an external BigInteger library?
Edit: I finally done a BigInteger class even if the Cheers and hth. - Alf's solution works like a charm
To get modulo 31 of a number you just need to sum up the digits in base 32, just like how you calculate modulo 3 and 9 of a decimal number
unsigned mod31(std::bitset<74> b) {
unsigned mod = 0;
while (!b.none()) {
mod += (b & std::bitset<74>(0x1F)).to_ulong();
b >>= 5;
}
while (mod > 31)
mod = (mod >> 5) + (mod & 0x1F);
return mod;
}
You can speedup the modulo calculation by running the additions in parallel like how its done here. The similar technique can be used to calculate modulo 3, 5, 7, 15... and 231 - 1
C - Algorithm for Bitwise operation on Modulus for number of not a power of 2
Is there any easy way to do modulus of 2^32 - 1 operation?
Logic to check the number is divisible by 3 or not?
However since the question is actually about base conversion and not about modulo as the title said, you need to do a real division for this purpose. Notice 1/b is 0.(1) in base b + 1, we have
1/31 = 0.000010000100001000010000100001...32 = 0.(00001)32
and then N/31 can be calculated like this
N/31 = N×2-5 + N×2-10 + N×2-15 + ...
uint128_t result = 0;
while (x)
{
x >>= 5;
result += x;
}
Since both modulo and division use shift-by-5, you can also do both them together in a single loop.
However the tricky part here is how to round the quotient properly. The above method will work for most values except some between a multiple of 31 and the next power of 2. I've found the way to correct the result for values up to a few thousands but yet to find a generic way for all values
You can see the same shift-and-add method being used to divide by 10 and by 3. There are more examples in the famous Hacker's Delight with proper rounding. I didn't have enough time to read through the book to understand how they implement the result correction part so maybe I'll get back to this later. If anyone has any idea to do that it'll be grateful.
One suggestion is to do the division in fixed-point. Just shift the value left so that we have enough fractional part to round later
uint128_t result = 0;
const unsigned num_fraction = 125 - 75 // 125 and 75 are the nearest multiple of 5
// or maybe 128 - 74 will also work
uint128_t x = UFI_Number << num_fraction;
while (x)
{
x >>= 5;
result += x;
}
// shift the result back and add the fractional bit to round
result = (result >> num_fraction) + ((result >> (num_fraction - 1)) & 1)
Note that your result above is incorrect. I've confirmed the result is CEOPPJ62MK6CPR1 from both Yaniv Shaked's answer and Wolfram alpha unless you use different symbols for the digits
This code seems to work. To guarantee the result I think you need to do additional testing. E.g. first with small numbers where you can compute the result directly.
Edit: Oh, now I noticed you posted the required result digits, and they match. Means it's generally good, but still not tested for corner cases.
#include <assert.h>
#include <algorithm> // std::reverse
#include <bitset>
#include <vector>
#include <iostream>
using namespace std;
template< class Type > using ref_ = Type&;
namespace base31
{
void mul2( ref_<vector<int>> digits )
{
int carry = 0;
for( ref_<int> d : digits )
{
const int local_sum = 2*d + carry;
d = local_sum % 31;
carry = local_sum / 31;
}
if( carry != 0 )
{
digits.push_back( carry );
}
}
void add1( ref_<vector<int>> digits )
{
int carry = 1;
for( ref_<int> d : digits )
{
const int local_sum = d + carry;
d = local_sum % 31;
carry = local_sum / 31;
}
if( carry != 0 )
{
digits.push_back( carry );
}
}
void divmod2( ref_<vector<int>> digits, ref_<int> mod )
{
int carry = 0;
for( int i = int( digits.size() ) - 1; i >= 0; --i )
{
ref_<int> d = digits[i];
const int divisor = d + 31*carry;
carry = divisor % 2;
d = divisor/2;
}
mod = carry;
if( digits.size() > 0 and digits.back() == 0 )
{
digits.resize( digits.size() - 1 );
}
}
}
int main() {
bitset<74> bits(
"10000000000000000000000000000101000001000001010000011101011111100010100010"
);
vector<int> reversed_binary;
for( const char ch : bits.to_string() ) { reversed_binary.push_back( ch - '0' ); }
vector<int> base31;
for( const int bit : reversed_binary )
{
base31::mul2( base31 );
if( bit != 0 )
{
base31::add1( base31 );
}
}
{ // Check the conversion to base31 by converting back to base 2, roundtrip:
vector<int> temp31 = base31;
int mod;
vector<int> base2;
while( temp31.size() > 0 )
{
base31::divmod2( temp31, mod );
base2.push_back( mod );
}
reverse( base2.begin(), base2.end() );
cout << "Original : " << bits.to_string() << endl;
cout << "Reconstituted: ";
string s;
for( const int bit : base2 ) { s += bit + '0'; cout << bit; }; cout << endl;
assert( s == bits.to_string() );
}
cout << "Base 31 digits (msd to lsd order): ";
for( int i = int( base31.size() ) - 1; i >= 0; --i )
{
cout << base31[i] << ' ';
}
cout << endl;
cout << "Mod 31 = " << base31[0] << endl;
}
Results with MinGW g++:
Original : 10000000000000000000000000000101000001000001010000011101011111100010100010
Reconstituted: 10000000000000000000000000000101000001000001010000011101011111100010100010
Base 31 digits (msd to lsd order): 12 14 24 25 25 19 6 2 22 20 6 12 25 27 1
Mod 31 = 1
I did not compile the psuedo code, but you can get the generate understanding of how to convert the number:
// Array for conversion of value to base-31 characters:
char base31Characters[] =
{
'0',
'1',
'2',
...
'X',
'Y'
};
void printUFINumber(__int128_t number)
{
string result = "";
while (number != 0)
{
var mod = number % 31;
result = base31Characters[mod] + result;
number = number / 31;
}
cout << number;
}

Is this an inefficent way to convert from a binary string to decimal value?

while(i < length)
{
pow = 1;
for(int j = 0; j < 8; j++, pow *=2)
{
ch += (str[j] - 48) * pow;
}
str = str.substr(8);
i+=8;
cout << ch;
ch = 0;
}
This seems to be slowing my program down a lot. Is it because of the string functions I'm using in there, or is this approach wrong in general. I know there's the way where you implement long division, but I wanted to see if that was actually more efficient than this method. I can't think of another way that doesn't use the same general algorithm, so maybe it's just my implementation that is the problem.
Perhaps you want might to look into using the standard library functions. They're probably at least as optimised as anything you run through the compiler:
#include <iostream>
#include <iomanip>
#include <cstdlib>
int main (void) {
const char *str = "10100101";
// Use str.c_str() if it's a real C++ string.
long int li = std::strtol (str, 0, 2);
std::cout
<< "binary string = " << str
<< ", decimal = " << li
<< ", hex = " << std::setbase (16) << li
<< '\n';
return 0;
}
The output is:
binary string = 10100101, decimal = 165, hex = a5
You are doing some things unnecessarily, like creating a new substring for each each loop. You could just use str[i + j] instead.
It is also not necessary to multiply 0 or 1 with the power. Just use an if-statement.
while(i < length)
{
pow = 1;
for(int j = 0; j < 8; j++, pow *=2)
{
if (str[i + j] == '1')
ch += pow;
}
i+=8;
cout << ch;
ch = 0;
}
This will at least run a bit faster.
short answer could be:
long int x = strtol(your_binary_c++_string.c_str(),(char **)NULL,2)
Probably you can use int or long int like below:
Just traverse the binary number step by step, starting from 0 to n-1, where n is the most significant bit(MSB) ,
multiply them with 2 with raising powers and add the sum together. E.g to convert 1000(which is binary equivalent of 8), just do the following
1 0 0 0 ==> going from right to left
0 x 2^0 = 0
0 x 2^1 = 0;
0 x 2^2 = 0;
1 x 2^3 = 8;
now add them together i.e 0+0+0+8 = 8; this the decimal equivalent of 1000. Please read the program below to have a better understanding how the concept
work. Note : The program works only for 16-bit binary numbers(non-floating) or less. Leave a comment if anything is not clear. You are bound to receive a reply.
// Program to convert binary to its decimal equivalent
#include <iostream>
#include <math.h>
int main()
{
int x;
int i=0,sum = 0;
// prompts the user to input a 16-bit binary number
std::cout<<" Enter the binary number (16-bit) : ";
std::cin>>x;
while ( i != 16 ) // runs 16 times
{
sum += (x%10) * pow(2,i);
x = x/10;
i++;
}
std::cout<<"\n The decimal equivalent is : "<<sum;
return 0;
}
How about something like:
int binstring_to_int(const std::string &str)
{
// 16 bits are 16 characters, but -1 since bits are numbered 0 to 15
std::string::size_type bitnum = str.length() - 1;
int value = 0;
for (auto ch : str)
{
value |= (ch == '1') << bitnum--;
}
return value;
}
It's the simplest I can think of. Note that this uses the new C++11 for-each loop construct, if your compiler can't handle it you can use
for (std::string::const_iterator i = str.begin(); i != str.end(); i++)
{
char ch = *i;
// ...
}
Minimize the number of operations and don't compute things more than once. Just multiply and move up:
unsigned int result = 0;
for (char * p = str; *p != 0; ++p)
{
result *= 2;
result += (*p - '0'); // this is either 0 or 1
}
The scheme is readily generalized to any base < 10.

Octal conversion using loops in C++

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 ;
}