Related
I have to take two numbers and find all numbers (inclusive) between those two numbers with the digits 6 or 8 in them, but not both. So an input of 6 8 would return 2, while an input of 60 69 would return 9 (as 68 isn't counted).
This is a very simple thing to do, but I have to do this in less than a second, even with numbers in the quadrillions. The fact that this is impossible to do itteratively makes me wonder if there's some basic trick to skip checking 99% of the numbers that I'm missing. The most I've been able to optimize this is by being able to make jumps of 10^[two less than the number of digits in the difference between the two numbers], let's define that exponent as d. I made my program make these jumps when the number had the digits 6 and 8, or neither of those digits, and ended in at least d zeros. If the number had neither the digits 6 and 8, the value of the number of numbers with 6 or 8 between 1 and 10^d is added to the number of special numbers (this first value that is added having been saved in an array in memory).
In any case, the best way I think I can demonstrate my attempted solution is by presenting my code. Though, if you have an suggestions for improving my question, feel free to make them.
#include <iostream>
int main() {
int_fast64_t low; //starting number
int_fast64_t high; //ending number
std::cin >> low >> high; std::cin.ignore();
/*Starts out holding the difference between high and low,
then will hold two less than the number of digits in that difference*/
int_fast64_t lowHighDifference = high - low;
//10 to various powers used to not have to itterate over every number between low & high
static int_fast64_t pow10[] = {0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
//The number of numbers with 6 xor 8 between 1 and 10^index
static int_fast64_t numspecial[] = {0, 2, 34, 434, 4930, 52562, 538594, 5371634, 52539010, 506405522};
//Find how large the jumps one can make are based on the difference between high and low
for (int_fast8_t itterator = 9; itterator > 0; itterator--) {
if (lowHighDifference > pow10[itterator]) {
/*This needs to have two fewer digits than the difference between low & high,
otherwise it risks not being used*/
lowHighDifference = itterator - 1;
itterator = 0;
}
}
/*Incremented by one every time a number with 6 xor 8 is ecountered,
and by numspecial[lowHighDifference] every time a number without 6 or 8,
and at least as many zeros at the end as pow10[lowHighDifference] is encountered*/
int_fast64_t specialNumbers = 0;
for (int_fast64_t itterator = low; itterator <= high; itterator++) {
char stringNum[21]; //long ints can't have more than 20 digits
/*Copy itterator into a string to check each digit individually,
while recording the length that string ends up being. */
int_fast8_t stringNumLength = sprintf(stringNum, "%ld", itterator),
/*Starts at 0, will turn to 6 or 8 with the first of those found,
then will be set to -1 if the other number is found */
sixOrEight = 0;
for (int_fast8_t stringNumItterator = 0; stringNumItterator < stringNumLength; stringNumItterator++) {
if (stringNum[stringNumItterator] == '8') {
if (sixOrEight == 6) {
sixOrEight = -1;
stringNumItterator = stringNumLength;
}
else
sixOrEight = 8;
}
else if (stringNum[stringNumItterator] == '6') {
if (sixOrEight == 8) {
sixOrEight = -1;
stringNumItterator = stringNumLength;
}
else
sixOrEight = 6;
}
}
/*The basic case in which a six or an eight was found. I don't know how I can optimize this,
but it's the main part slowing this program down. */
if (sixOrEight > 0) {
specialNumbers++;
}
else if (lowHighDifference > 0) {
//If neither six or eight were found
if (sixOrEight == 0) {
if (itterator % pow10[lowHighDifference] == 0 && pow10[lowHighDifference] < (high - itterator)) {
specialNumbers += numspecial[lowHighDifference];
itterator += pow10[lowHighDifference] - 1;
}
} //If sixOrEight is < 0 and itterator has at least as many zeros at the end as pow10[lowHighDifference]
else if (itterator % pow10[lowHighDifference] == 0) {
//Add 10^lowHighDifference to itterator without adding to specialNumbers
itterator += pow10[lowHighDifference] - 1;
}
}
}
std::cout << specialNumbers;
return 0;
}
Full solution at bottom of this post
It took a few hours to cook this up, but I think I have the optimal solution. Thanks for providing this challenge. Number computational problems are a hobby of mine (to a fault).
TERMINOLOGY
First some terminology I invented just for this problem:
NQ or "Non-qualified". An NQ number is one that has neither a 6 nor 8 in its set of digits.
Q6 or "Qualified by 6" is any number with a 6 in its sets of digits, but no eights.
Q8 or "Qualified by 8" is any number with a 8 in its sets of digits, but no sixes.
PNQ or "Permanently non-qualified". This is a number with both a 6 or 8 in it.
Any NQ number can become qualified simply by appending a 6 or 8 to the end of it. (e.g. 123 is NQ, but 1236 is "qualified")
The reason why I used this "qualified" term is because the solution needs to be thought in terms of building a numbers as a string of digits from left to right. For example, a non-qualified number such as 123 can become qualified simply by appending a 6 onto it. By appending a 6 onto 123, the number becomes 1236 and is Q6.
Any qualified number can become permanently non-qualified by appending a 6 or 8 to it such that it has both digits. For example, 654 is Q6, but if we append an 8 onto it, it comes permanently non-qualified. Any additional digits prepended onto this number will still result in the number being PNQ.
Slow solution
So let's introduce the first batch of code. A formalized enum of what I just discussed above:
enum class NumberType : int
{
NQ, // NQ is "non-qualifying". It's a number with neither a six or an eight
Q6, // Q6 is "qualified by 6". It's a number with at least a single six digit, but no eights
Q8, // Q8 is "qualified by 8". It's a number with at least a single eight digit, but no sixes
PNQ // PNQ is "permanently non qualified". It's a number with both a six and an eight in it
};
And let's introduce a helper function that can take any 64-bit number and tell us what type it is:
NumberType GetNumberType(uint64_t value)
{
uint64_t sixCount = 0;
uint64_t eightCount = 0;
NumberType result = NumberType::NQ;
while (value > 0)
{
uint64_t lastDigit = value % 10;
value /= 10;
if (lastDigit == 6)
{
sixCount++;
}
else if (lastDigit == 8)
{
eightCount++;
}
}
if (sixCount && eightCount)
{
result = NumberType::PNQ;
}
else if (sixCount)
{
result = NumberType::Q6;
}
else if (eightCount)
{
result = NumberType::Q8;
}
else
{
result = NumberType::NQ;
}
return result;
}
At this point we could easily build a brute force solution to compute the count of Q6 or Q8 numbers within a given range.
uint64_t GetSixXorEightCount_BruteForceSlow(uint64_t start, uint64_t end)
{
uint64_t count = 0;
for (auto x = start; x <= end; x++)
{
NumberType nt = GetNumberType(x);
count += ((nt == NumberType::Q6) || (nt == NumberType::Q8)) ? 1 : 0;
}
return count;
}
But once we start to get into a range with billions numbers that won't scale.
Number patterns
Now something about digits I noticed.
Take all the single digit numbers excluding zero:
7 NQ numbers (1,2,3,4,5,7,9)
1 Q6 number (6)
1 Q8 number (8)
0 in PNQ
Take all the two digit numbers between 10 and 99. If you do a cursory scan of those numbers, you'll find that the following stats hold true:
56 NQ numbers (e.g. 23, 45, 79, etc..)
16 Q6 numbers (60-67, 69, 16,26,36,46,56,76,96)
16 Q8 numbers (80-85, 87-89, 18,28,38,48,58,78,96)
2 PNQ numbers (68 and 86)
And to compute the stats for all 3 digit numbers, you don't have to do a brute force search. You'll realize the following:
All the NQ numbers in the 2 digit range can be appended with one of 8 digits to compute the NQ set. Hence the total number of NQ for 3 digits is simply 56*8.
All the Q6 and Q8 numbers can remain qualified by appending one of 9 digits onto it. Further, any NQ number from the 2-digit range can be added to the Q6 or Q8 set simply by adding a 6 or 8.
And so it follows, a general formlua for figuring out how many types of numbers are in any set of N digit numbers:
countof_nq(N) == countof_nq(N-1)*8
countof_q6(N) == countof_q6(N-1)*9 + countof_nq(N-1)
countof_q8(N) == countof_q8(N-1)*9 + countof_nq(N-1)
countof_pnq(N) == countof_pnq(N-1) * 10 + countof_q6(N-1) + countof_q8(N-1)
Now if the problem space was "compute the count of N digit numbers with 6 xor 8", then the recursion function would be easy. But how do you compute ranges of numbers within different digit boundaries?
Example break down
Let's say you want to find the range of qualifying numbers between 125 and 455.
You start by recursively breaking the problem down from 125-455 by chopping off digits.
Solve for 12-45 first, which requires solving for 1-4 before then. Then apply the formula for counting up into the next digit range. But you have to add a repair step to uncount the numbers not in range (120-124 and 456-459).
SolveFor(125-455):
SolveFor(12-45)
SolveFor(1-4) => {Q6:0, Q8:0, NQ: 4}
Compute for 10-49 => {Q6: 4, Q8: 4, NQ: 32}
Repair for 12-45 by uncounting 10,11,46,47,48,and 49 from the stats set => {{Q6: 3, Q8: 3, NQ: 28}
Compute for 120-459 => {Q6:55, Q8:55, NQ: 224}
Repair for 125-455 by uncounting 120-124 and uncounting for 456-459 => {Q6:54, Q8:54, NQ: 217}
Final Solution
#include <iostream>
using namespace std;
enum class NumberType : int
{
NQ, // NQ is "non-qualifying". It's a number with neither a six or an eight
Q6, // Q6 is "qualified by 6". It's a number with at least a single six digit, but no eights
Q8, // Q8 is "qualified by 8". It's a number with at least a single eight digit, but no sixes
PNQ // PNQ is "permanently non qualified". It's a number with both a six and an eight in it
};
struct range_stats
{
uint64_t nq; // number of "non-qualifying numbers" that have neither 6 nor 8 in any digit
uint64_t pnq; // number of "permanently non-qualifying" numbers tht have both a 6 or 8
uint64_t q6; // number of qualifying numbers that have at least one occurance of 6, but not 8
uint64_t q8; // number of qualifying numbers that have at least one occurance of 8, but not 6
};
NumberType GetNumberType(uint64_t value)
{
uint64_t sixCount = 0;
uint64_t eightCount = 0;
NumberType result;
while (value > 0)
{
uint64_t lastDigit = value % 10;
value /= 10;
if (lastDigit == 6)
{
sixCount++;
}
else if (lastDigit == 8)
{
eightCount++;
}
}
if (sixCount && eightCount)
{
result = NumberType::PNQ;
}
else if (sixCount)
{
result = NumberType::Q6;
}
else if (eightCount)
{
result = NumberType::Q8;
}
else
{
result = NumberType::NQ;
}
return result;
}
void DeductStats(range_stats& stats, NumberType nt)
{
switch (nt)
{
case NumberType::Q6:
{
stats.q6--;
break;
}
case NumberType::Q8:
{
stats.q8--;
break;
}
case NumberType::NQ:
{
stats.nq--;
break;
}
case NumberType::PNQ:
{
stats.pnq--;
break;
}
}
}
void AddStats(range_stats& stats, NumberType nt)
{
switch (nt)
{
case NumberType::Q6:
{
stats.q6++;
break;
}
case NumberType::Q8:
{
stats.q8++;
break;
}
case NumberType::NQ:
{
stats.nq++;
break;
}
case NumberType::PNQ:
{
stats.pnq++;
break;
}
}
}
void GetStatsForRange(uint64_t start, uint64_t end, range_stats& stats)
{
// ASSUMES START AND END HAVE THE SAME NUMBER OF DIGITS
if (end < 10)
{
uint64_t sum = 0;
stats = {};
for (auto i = start; i <= end; i++)
{
if (i == 6)
{
stats.q6++;
}
else if (i == 8)
{
stats.q8++;
}
else if (i > 0)
{
stats.nq++;
}
}
}
else
{
uint64_t newStart = start / 10;
uint64_t newEnd = end / 10;
uint64_t repairStart = (start / 10) * 10; // convert 123 to 120
uint64_t repairEnd = (end / 10) * 10 + 9; // convert 567 to 569
range_stats lowerStats = {};
GetStatsForRange(newStart, newEnd, lowerStats);
stats.nq = lowerStats.nq * 8;
stats.q6 = lowerStats.q6 * 9 + lowerStats.nq;
stats.q8 = lowerStats.q8 * 9 + lowerStats.nq;
stats.pnq = lowerStats.pnq * 10 + lowerStats.q6 + lowerStats.q8;
// now repair the stats by accounting for the ones that aren't in range
for (uint64_t i = repairStart; i < start; i++)
{
auto nt = GetNumberType(i);
DeductStats(stats, nt);
}
for (uint64_t i = repairEnd; i > end; i--)
{
auto nt = GetNumberType(i);
DeductStats(stats, nt);
}
}
}
bool InRange(uint64_t value, uint64_t minimum, uint64_t maximum)
{
return ((value >= minimum) && (value <= maximum));
}
bool IntersectionOfRanges(uint64_t levelStart, uint64_t levelEnd, uint64_t start, uint64_t end, uint64_t& newStart, uint64_t& newEnd)
{
// ASSERT START <= END
bool startInRange = InRange(start, levelStart, levelEnd);
bool endInRange = InRange(end, levelStart, levelEnd);
if ((end < levelStart) || (start > levelEnd))
{
return false; // no intersection
}
if (!startInRange && endInRange)
{
newStart = levelStart;
newEnd = end;
}
else if (startInRange && endInRange)
{
newStart = start;
newEnd = end;
}
else if (startInRange)
{
newStart = start;
newEnd = levelEnd;
}
else
{
newStart = levelStart;
newEnd = levelEnd;
}
return true;
}
void bruteForceTest(uint64_t start, uint64_t end, range_stats& stats)
{
stats = {};
for (auto i = start; i <= end; i++)
{
auto nt = GetNumberType(i);
AddStats(stats, nt);
}
}
uint64_t GetSixXorEightCount(uint64_t start, uint64_t end)
{
range_stats stats = {};
range_stats expected = {};
range_stats results = {};
if (start == 0)
{
start = 1;
}
if (start > end)
{
return 0;
}
uint64_t levelStart = 1;
uint64_t levelEnd = 9;
while (levelStart <= end)
{
uint64_t normalizedStart;
uint64_t normalizedEnd;
if (IntersectionOfRanges(levelStart, levelEnd, start, end, normalizedStart, normalizedEnd))
{
stats = {};
GetStatsForRange(normalizedStart, normalizedEnd, stats);
results.nq += stats.nq;
results.q6 += stats.q6;
results.q8 += stats.q8;
results.pnq += stats.pnq;
}
levelStart = levelStart * 10;
levelEnd = levelEnd * 10 + 9;
}
cout << "For the range of numbers between " << start << " and " << end << endl;
cout << "Q6: " << results.q6 << endl;
cout << "Q8: " << results.q8 << endl;
cout << "NQ: " << results.nq << endl;
cout << "PNQ: " << results.pnq << endl;
//cout << "Brute force computing expected" << endl;
//bruteForceTest(start, end, expected);
//cout << "Expected Q6: " << expected.q6 << endl;
//cout << "Expected Q8: " << expected.q8 << endl;
//cout << "Expected NQ: " << expected.nq << endl;
//cout << "Expected PNQ: " << expected.pnq << endl;
return results.q6 + results.q8;
}
int main()
{
uint64_t start = 0;
uint64_t end = 0;
cout << "Starting number:\n";
cin >> start;
cout << "Ending number:\n";
cin >> end;
uint64_t result = GetSixXorEightCount(start, end);
std::cout << "There are " << result << " qualifying numbers in range that have a six or eight, but not both\n";
return 0;
}
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;
}
I wrote a 'simple' (it took me 30 minutes) program that converts decimal number to binary. I am SURE that there's a lot simpler way so can you show me?
Here's the code:
#include <iostream>
#include <stdlib.h>
using namespace std;
int a1, a2, remainder;
int tab = 0;
int maxtab = 0;
int table[0];
int main()
{
system("clear");
cout << "Enter a decimal number: ";
cin >> a1;
a2 = a1; //we need our number for later on so we save it in another variable
while (a1!=0) //dividing by two until we hit 0
{
remainder = a1%2; //getting a remainder - decimal number(1 or 0)
a1 = a1/2; //dividing our number by two
maxtab++; //+1 to max elements of the table
}
maxtab--; //-1 to max elements of the table (when dividing finishes it adds 1 additional elemnt that we don't want and it's equal to 0)
a1 = a2; //we must do calculations one more time so we're gatting back our original number
table[0] = table[maxtab]; //we set the number of elements in our table to maxtab (we don't get 10's of 0's)
while (a1!=0) //same calculations 2nd time but adding every 1 or 0 (remainder) to separate element in table
{
remainder = a1%2; //getting a remainder
a1 = a1/2; //dividing by 2
table[tab] = remainder; //adding 0 or 1 to an element
tab++; //tab (element count) increases by 1 so next remainder is saved in another element
}
tab--; //same as with maxtab--
cout << "Your binary number: ";
while (tab>=0) //until we get to the 0 (1st) element of the table
{
cout << table[tab] << " "; //write the value of an element (0 or 1)
tab--; //decreasing by 1 so we show 0's and 1's FROM THE BACK (correct way)
}
cout << endl;
return 0;
}
By the way it's complicated but I tried my best.
edit - Here is the solution I ended up using:
std::string toBinary(int n)
{
std::string r;
while(n!=0) {r=(n%2==0 ?"0":"1")+r; n/=2;}
return r;
}
std::bitset has a .to_string() method that returns a std::string holding a text representation in binary, with leading-zero padding.
Choose the width of the bitset as needed for your data, e.g. std::bitset<32> to get 32-character strings from 32-bit integers.
#include <iostream>
#include <bitset>
int main()
{
std::string binary = std::bitset<8>(128).to_string(); //to binary
std::cout<<binary<<"\n";
unsigned long decimal = std::bitset<8>(binary).to_ulong();
std::cout<<decimal<<"\n";
return 0;
}
EDIT: Please do not edit my answer for Octal and Hexadecimal. The OP specifically asked for Decimal To Binary.
The following is a recursive function which takes a positive integer and prints its binary digits to the console.
Alex suggested, for efficiency, you may want to remove printf() and store the result in memory... depending on storage method result may be reversed.
/**
* Takes a unsigned integer, converts it into binary and prints it to the console.
* #param n the number to convert and print
*/
void convertToBinary(unsigned int n)
{
if (n / 2 != 0) {
convertToBinary(n / 2);
}
printf("%d", n % 2);
}
Credits to UoA ENGGEN 131
*Note: The benefit of using an unsigned int is that it can't be negative.
You can use std::bitset to convert a number to its binary format.
Use the following code snippet:
std::string binary = std::bitset<8>(n).to_string();
I found this on stackoverflow itself. I am attaching the link.
A pretty straight forward solution to print binary:
#include <iostream>
using namespace std;
int main()
{
int num,arr[64];
cin>>num;
int i=0,r;
while(num!=0)
{
r = num%2;
arr[i++] = r;
num /= 2;
}
for(int j=i-1;j>=0;j--){
cout<<arr[j];
}
}
Non recursive solution:
#include <iostream>
#include<string>
std::string toBinary(int n)
{
std::string r;
while(n!=0) {r=(n%2==0 ?"0":"1")+r; n/=2;}
return r;
}
int main()
{
std::string i= toBinary(10);
std::cout<<i;
}
Recursive solution:
#include <iostream>
#include<string>
std::string r="";
std::string toBinary(int n)
{
r=(n%2==0 ?"0":"1")+r;
if (n / 2 != 0) {
toBinary(n / 2);
}
return r;
}
int main()
{
std::string i=toBinary(10);
std::cout<<i;
}
An int variable is not in decimal, it's in binary. What you're looking for is a binary string representation of the number, which you can get by applying a mask that filters individual bits, and then printing them:
for( int i = sizeof(value)*CHAR_BIT-1; i>=0; --i)
cout << value & (1 << i) ? '1' : '0';
That's the solution if your question is algorithmic. If not, you should use the std::bitset class to handle this for you:
bitset< sizeof(value)*CHAR_BIT > bits( value );
cout << bits.to_string();
Here are two approaches. The one is similar to your approach
#include <iostream>
#include <string>
#include <limits>
#include <algorithm>
int main()
{
while ( true )
{
std::cout << "Enter a non-negative number (0-exit): ";
unsigned long long x = 0;
std::cin >> x;
if ( !x ) break;
const unsigned long long base = 2;
std::string s;
s.reserve( std::numeric_limits<unsigned long long>::digits );
do { s.push_back( x % base + '0' ); } while ( x /= base );
std::cout << std::string( s.rbegin(), s.rend() ) << std::endl;
}
}
and the other uses std::bitset as others suggested.
#include <iostream>
#include <string>
#include <bitset>
#include <limits>
int main()
{
while ( true )
{
std::cout << "Enter a non-negative number (0-exit): ";
unsigned long long x = 0;
std::cin >> x;
if ( !x ) break;
std::string s =
std::bitset<std::numeric_limits<unsigned long long>::digits>( x ).to_string();
std::string::size_type n = s.find( '1' );
std::cout << s.substr( n ) << std::endl;
}
}
The conversion from natural number to a binary string:
string toBinary(int n) {
if (n==0) return "0";
else if (n==1) return "1";
else if (n%2 == 0) return toBinary(n/2) + "0";
else if (n%2 != 0) return toBinary(n/2) + "1";
}
For this , In C++ you can use itoa() function .This function convert any Decimal integer to binary, decimal , hexadecimal and octal number.
#include<bits/stdc++.h>
using namespace std;
int main(){
int a;
char res[1000];
cin>>a;
itoa(a,res,10);
cout<<"Decimal- "<<res<<endl;
itoa(a,res,2);
cout<<"Binary- "<<res<<endl;
itoa(a,res,16);
cout<<"Hexadecimal- "<<res<<endl;
itoa(a,res,8);
cout<<"Octal- "<<res<<endl;return 0;
}
However, it is only supported by specific compilers.
You can see also: itoa - C++ Reference
Here is modern variant that can be used for ints of different sizes.
#include <type_traits>
#include <bitset>
template<typename T>
std::enable_if_t<std::is_integral_v<T>,std::string>
encode_binary(T i){
return std::bitset<sizeof(T) * 8>(i).to_string();
}
Your solution needs a modification. The final string should be reversed before returning:
std::reverse(r.begin(), r.end());
return r;
DECIMAL TO BINARY NO ARRAYS USED *made by Oya:
I'm still a beginner, so this code will only use loops and variables xD...
Hope you like it. This can probably be made simpler than it is...
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
int main()
{
int i;
int expoentes; //the sequence > pow(2,i) or 2^i
int decimal;
int extra; //this will be used to add some 0s between the 1s
int x = 1;
cout << "\nThis program converts natural numbers into binary code\nPlease enter a Natural number:";
cout << "\n\nWARNING: Only works until ~1.073 millions\n";
cout << " To exit, enter a negative number\n\n";
while(decimal >= 0){
cout << "\n----- // -----\n\n";
cin >> decimal;
cout << "\n";
if(decimal == 0){
cout << "0";
}
while(decimal >= 1){
i = 0;
expoentes = 1;
while(decimal >= expoentes){
i++;
expoentes = pow(2,i);
}
x = 1;
cout << "1";
decimal -= pow(2,i-x);
extra = pow(2,i-1-x);
while(decimal < extra){
cout << "0";
x++;
extra = pow(2,i-1-x);
}
}
}
return 0;
}
here a simple converter by using std::string as container. it allows a negative value.
#include <iostream>
#include <string>
#include <limits>
int main()
{
int x = -14;
int n = std::numeric_limits<int>::digits - 1;
std::string s;
s.reserve(n + 1);
do
s.push_back(((x >> n) & 1) + '0');
while(--n > -1);
std::cout << s << '\n';
}
This is a more simple program than ever
//Program to convert Decimal into Binary
#include<iostream>
using namespace std;
int main()
{
long int dec;
int rem,i,j,bin[100],count=-1;
again:
cout<<"ENTER THE DECIMAL NUMBER:- ";
cin>>dec;//input of Decimal
if(dec<0)
{
cout<<"PLEASE ENTER A POSITIVE DECIMAL";
goto again;
}
else
{
cout<<"\nIT's BINARY FORM IS:- ";
for(i=0;dec!=0;i++)//making array of binary, but reversed
{
rem=dec%2;
bin[i]=rem;
dec=dec/2;
count++;
}
for(j=count;j>=0;j--)//reversed binary is printed in correct order
{
cout<<bin[j];
}
}
return 0;
}
There is in fact a very simple way to do so. What we do is using a recursive function which is given the number (int) in the parameter. It is pretty easy to understand. You can add other conditions/variations too. Here is the code:
int binary(int num)
{
int rem;
if (num <= 1)
{
cout << num;
return num;
}
rem = num % 2;
binary(num / 2);
cout << rem;
return rem;
}
// function to convert decimal to binary
void decToBinary(int n)
{
// array to store binary number
int binaryNum[1000];
// counter for binary array
int i = 0;
while (n > 0) {
// storing remainder in binary array
binaryNum[i] = n % 2;
n = n / 2;
i++;
}
// printing binary array in reverse order
for (int j = i - 1; j >= 0; j--)
cout << binaryNum[j];
}
refer :-
https://www.geeksforgeeks.org/program-decimal-binary-conversion/
or
using function :-
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;cin>>n;
cout<<bitset<8>(n).to_string()<<endl;
}
or
using left shift
#include<bits/stdc++.h>
using namespace std;
int main()
{
// here n is the number of bit representation we want
int n;cin>>n;
// num is a number whose binary representation we want
int num;
cin>>num;
for(int i=n-1;i>=0;i--)
{
if( num & ( 1 << i ) ) cout<<1;
else cout<<0;
}
}
#include <iostream>
#include <bitset>
#define bits(x) (std::string( \
std::bitset<8>(x).to_string<char,std::string::traits_type, std::string::allocator_type>() ).c_str() )
int main() {
std::cout << bits( -86 >> 1 ) << ": " << (-86 >> 1) << std::endl;
return 0;
}
Okay.. I might be a bit new to C++, but I feel the above examples don't quite get the job done right.
Here's my take on this situation.
char* DecimalToBinary(unsigned __int64 value, int bit_precision)
{
int length = (bit_precision + 7) >> 3 << 3;
static char* binary = new char[1 + length];
int begin = length - bit_precision;
unsigned __int64 bit_value = 1;
for (int n = length; --n >= begin; )
{
binary[n] = 48 | ((value & bit_value) == bit_value);
bit_value <<= 1;
}
for (int n = begin; --n >= 0; )
binary[n] = 48;
binary[length] = 0;
return binary;
}
#value = The Value we are checking.
#bit_precision = The highest left most bit to check for.
#Length = The Maximum Byte Block Size. E.g. 7 = 1 Byte and 9 = 2 Byte, but we represent this in form of bits so 1 Byte = 8 Bits.
#binary = just some dumb name I gave to call the array of chars we are setting. We set this to static so it won't be recreated with every call. For simply getting a result and display it then this works good, but if let's say you wanted to display multiple results on a UI they would all show up as the last result. This can be fixed by removing static, but make sure you delete [] the results when you are done with it.
#begin = This is the lowest index that we are checking. Everything beyond this point is ignored. Or as shown in 2nd loop set to 0.
#first loop - Here we set the value to 48 and basically add a 0 or 1 to 48 based on the bool value of (value & bit_value) == bit_value. If this is true the char is set to 49. If this is false the char is set to 48. Then we shift the bit_value or basically multiply it by 2.
#second loop - Here we set all the indexes we ignored to 48 or '0'.
SOME EXAMPLE OUTPUTS!!!
int main()
{
int val = -1;
std::cout << DecimalToBinary(val, 1) << '\n';
std::cout << DecimalToBinary(val, 3) << '\n';
std::cout << DecimalToBinary(val, 7) << '\n';
std::cout << DecimalToBinary(val, 33) << '\n';
std::cout << DecimalToBinary(val, 64) << '\n';
std::cout << "\nPress any key to continue. . .";
std::cin.ignore();
return 0;
}
00000001 //Value = 2^1 - 1
00000111 //Value = 2^3 - 1.
01111111 //Value = 2^7 - 1.
0000000111111111111111111111111111111111 //Value = 2^33 - 1.
1111111111111111111111111111111111111111111111111111111111111111 //Value = 2^64 - 1.
SPEED TESTS
Original Question's Answer: "Method: toBinary(int);"
Executions: 10,000 , Total Time (Milli): 4701.15 , Average Time (Nanoseconds): 470114
My Version: "Method: DecimalToBinary(int, int);"
//Using 64 Bit Precision.
Executions: 10,000,000 , Total Time (Milli): 3386 , Average Time (Nanoseconds): 338
//Using 1 Bit Precision.
Executions: 10,000,000, Total Time (Milli): 634, Average Time (Nanoseconds): 63
Below is simple C code that converts binary to decimal and back again. I wrote it long ago for a project in which the target was an embedded processor and the development tools had a stdlib that was way too big for the firmware ROM.
This is generic C code that does not use any library, nor does it use division or the remainder (%) operator (which is slow on some embedded processors), nor does it use any floating point, nor does it use any table lookup nor emulate any BCD arithmetic. What it does make use of is the type long long, more specifically unsigned long long (or uint64_t), so if your embedded processor (and the C compiler that goes with it) cannot do 64-bit integer arithmetic, this code is not for your application. Otherwise, I think this is production quality C code (maybe after changing long to int32_t and unsigned long long to uint64_t). I have run this overnight to test it for every 2³² signed integer values and there is no error in conversion in either direction.
We had a C compiler/linker that could generate executables and we needed to do what we could do without any stdlib (which was a pig). So no printf() nor scanf(). Not even an sprintf() nor sscanf(). But we still had a user interface and had to convert base-10 numbers into binary and back. (We also made up our own malloc()-like utility also and our own transcendental math functions too.)
So this was how I did it (the main program and calls to stdlib were there for testing this thing on my mac, not for the embedded code). Also, because some older dev systems don't recognize "int64_t" and "uint64_t" and similar types, the types long long and unsigned long long are used and assumed to be the same. And long is assumed to be 32 bits. I guess I could have typedefed it.
// returns an error code, 0 if no error,
// -1 if too big, -2 for other formatting errors
int decimal_to_binary(char *dec, long *bin)
{
int i = 0;
int past_leading_space = 0;
while (i <= 64 && !past_leading_space) // first get past leading spaces
{
if (dec[i] == ' ')
{
i++;
}
else
{
past_leading_space = 1;
}
}
if (!past_leading_space)
{
return -2; // 64 leading spaces does not a number make
}
// at this point the only legitimate remaining
// chars are decimal digits or a leading plus or minus sign
int negative = 0;
if (dec[i] == '-')
{
negative = 1;
i++;
}
else if (dec[i] == '+')
{
i++; // do nothing but go on to next char
}
// now the only legitimate chars are decimal digits
if (dec[i] == '\0')
{
return -2; // there needs to be at least one good
} // digit before terminating string
unsigned long abs_bin = 0;
while (i <= 64 && dec[i] != '\0')
{
if ( dec[i] >= '0' && dec[i] <= '9' )
{
if (abs_bin > 214748364)
{
return -1; // this is going to be too big
}
abs_bin *= 10; // previous value gets bumped to the left one digit...
abs_bin += (unsigned long)(dec[i] - '0'); // ... and a new digit appended to the right
i++;
}
else
{
return -2; // not a legit digit in text string
}
}
if (dec[i] != '\0')
{
return -2; // not terminated string in 64 chars
}
if (negative)
{
if (abs_bin > 2147483648)
{
return -1; // too big
}
*bin = -(long)abs_bin;
}
else
{
if (abs_bin > 2147483647)
{
return -1; // too big
}
*bin = (long)abs_bin;
}
return 0;
}
void binary_to_decimal(char *dec, long bin)
{
unsigned long long acc; // 64-bit unsigned integer
if (bin < 0)
{
*(dec++) = '-'; // leading minus sign
bin = -bin; // make bin value positive
}
acc = 989312855LL*(unsigned long)bin; // very nearly 0.2303423488 * 2^32
acc += 0x00000000FFFFFFFFLL; // we need to round up
acc >>= 32;
acc += 57646075LL*(unsigned long)bin;
// (2^59)/(10^10) = 57646075.2303423488 = 57646075 + (989312854.979825)/(2^32)
int past_leading_zeros = 0;
for (int i=9; i>=0; i--) // maximum number of digits is 10
{
acc <<= 1;
acc += (acc<<2); // an efficient way to multiply a long long by 10
// acc *= 10;
unsigned int digit = (unsigned int)(acc >> 59); // the digit we want is in bits 59 - 62
if (digit > 0)
{
past_leading_zeros = 1;
}
if (past_leading_zeros)
{
*(dec++) = '0' + digit;
}
acc &= 0x07FFFFFFFFFFFFFFLL; // mask off this digit and go on to the next digit
}
if (!past_leading_zeros) // if all digits are zero ...
{
*(dec++) = '0'; // ... put in at least one zero digit
}
*dec = '\0'; // terminate string
}
#if 1
#include <stdlib.h>
#include <stdio.h>
int main (int argc, const char* argv[])
{
char dec[64];
long bin, result1, result2;
unsigned long num_errors;
long long long_long_bin;
num_errors = 0;
for (long_long_bin=-2147483648LL; long_long_bin<=2147483647LL; long_long_bin++)
{
bin = (long)long_long_bin;
if ((bin&0x00FFFFFFL) == 0)
{
printf("bin = %ld \n", bin); // this is to tell us that things are moving along
}
binary_to_decimal(dec, bin);
decimal_to_binary(dec, &result1);
sscanf(dec, "%ld", &result2); // decimal_to_binary() should do the same as this sscanf()
if (bin != result1 || bin != result2)
{
num_errors++;
printf("bin = %ld, result1 = %ld, result2 = %ld, num_errors = %ld, dec = %s \n",
bin, result1, result2, num_errors, dec);
}
}
printf("num_errors = %ld \n", num_errors);
return 0;
}
#else
#include <stdlib.h>
#include <stdio.h>
int main (int argc, const char* argv[])
{
char dec[64];
long bin;
printf("bin = ");
scanf("%ld", &bin);
while (bin != 0)
{
binary_to_decimal(dec, bin);
printf("dec = %s \n", dec);
printf("bin = ");
scanf("%ld", &bin);
}
return 0;
}
#endif
My way of converting decimal to binary in C++. But since we are using mod, this function will work in case of hexadecimal or octal also. You can also specify bits. This function keeps calculating the lowest significant bit and place it on the end of the string. If you are not so similar to this method than you can vist: https://www.wikihow.com/Convert-from-Decimal-to-Binary
#include <bits/stdc++.h>
using namespace std;
string itob(int bits, int n) {
int count;
char str[bits + 1]; // +1 to append NULL character.
str[bits] = '\0'; // The NULL character in a character array flags the end
// of the string, not appending it may cause problems.
count = bits - 1; // If the length of a string is n, than the index of the
// last character of the string will be n - 1. Cause the
// index is 0 based not 1 based. Try yourself.
do {
if (n % 2)
str[count] = '1';
else
str[count] = '0';
n /= 2;
count--;
} while (n > 0);
while (count > -1) {
str[count] = '0';
count--;
}
return str;
}
int main() {
cout << itob(1, 0) << endl; // 0 in 1 bit binary.
cout << itob(2, 1) << endl; // 1 in 2 bit binary.
cout << itob(3, 2) << endl; // 2 in 3 bit binary.
cout << itob(4, 4) << endl; // 4 in 4 bit binary.
cout << itob(5, 15) << endl; // 15 in 5 bit binary.
cout << itob(6, 30) << endl; // 30 in 6 bit binary.
cout << itob(7, 61) << endl; // 61 in 7 bit binary.
cout << itob(8, 127) << endl; // 127 in 8 bit binary.
return 0;
}
The Output:
0
01
010
0100
01111
011110
0111101
01111111
Since you asked for a simple way, I am sharing this answer, after 8 years
Here is the expression!
Is it not interesting when there is no if condition, and we can get 0 or 1 with just a simple expression?
Well yes, NO if, NO long division
Here is what each variable means
Note: variable is the orange highlighted ones
Number: 0-infinity (a value to be converted to binary)
binary holder: 1 / 2 / 4 / 8 / 16 / 32 / ... (Place of binary needed, just like tens, hundreds)
Result: 0 or 1
If you want to make binary holder from 1 / 2 / 4 / 8 / 16 /... to 1 / 2 / 3 / 4 / 5/...
then use this expression
The procedure is simple for the second expression
First, the number variable is always, your number needed, and its stable.
Second the binary holder variable needs to be changed ,in a for loop, by +1 for the second image, x2 for the first image
I don't know c++ a lot ,here is a js code,for your understanding
function FindBinary(Number) {
var x,i,BinaryValue = "",binaryHolder = 1;
for (i = 1; Math.pow(2, i) <= Number; i++) {}//for trimming, you can even remove this and set i to 7,see the result
for (x = 1; x <= i; x++) {
var Algorithm = ((Number - (Number % binaryHolder)) / binaryHolder) % 2;//Main algorithm
BinaryValue = Algorithm + BinaryValue;
binaryHolder += binaryHolder;
}
return BinaryValue;
}
console.log(FindBinary(17));//your number
more ever, I think language doesn't matters a lot for algorithm questions
You want to do something like:
cout << "Enter a decimal number: ";
cin >> a1;
cout << setbase(2);
cout << a1
#include "stdafx.h"
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int main() {
// Initialize Variables
double x;
int xOct;
int xHex;
//Initialize a variable that stores the order if the numbers in binary/sexagesimal base
vector<int> rem;
//Get Demical value
cout << "Number (demical base): ";
cin >> x;
//Set the variables
xOct = x;
xHex = x;
//Get the binary value
for (int i = 0; x >= 1; i++) {
rem.push_back(abs(remainder(x, 2)));
x = floor(x / 2);
}
//Print binary value
cout << "Binary: ";
int n = rem.size();
while (n > 0) {
n--;
cout << rem[n];
} cout << endl;
//Print octal base
cout << oct << "Octal: " << xOct << endl;
//Print hexademical base
cout << hex << "Hexademical: " << xHex << endl;
system("pause");
return 0;
}
#include <iostream>
using namespace std;
int main()
{
int a,b;
cin>>a;
for(int i=31;i>=0;i--)
{
b=(a>>i)&1;
cout<<b;
}
}
HOPE YOU LIKE THIS SIMPLE CODE OF CONVERSION FROM DECIMAL TO BINARY
#include<iostream>
using namespace std;
int main()
{
int input,rem,res,count=0,i=0;
cout<<"Input number: ";
cin>>input;`enter code here`
int num=input;
while(input > 0)
{
input=input/2;
count++;
}
int arr[count];
while(num > 0)
{
arr[i]=num%2;
num=num/2;
i++;
}
for(int i=count-1 ; i>=0 ; i--)
{
cout<<" " << arr[i]<<" ";
}
return 0;
}
#include <iostream>
// x is our number to test
// pow is a power of 2 (e.g. 128, 64, 32, etc...)
int printandDecrementBit(int x, int pow)
{
// Test whether our x is greater than some power of 2 and print the bit
if (x >= pow)
{
std::cout << "1";
// If x is greater than our power of 2, subtract the power of 2
return x - pow;
}
else
{
std::cout << "0";
return x;
}
}
int main()
{
std::cout << "Enter an integer between 0 and 255: ";
int x;
std::cin >> x;
x = printandDecrementBit(x, 128);
x = printandDecrementBit(x, 64);
x = printandDecrementBit(x, 32);
x = printandDecrementBit(x, 16);
std::cout << " ";
x = printandDecrementBit(x, 8);
x = printandDecrementBit(x, 4);
x = printandDecrementBit(x, 2);
x = printandDecrementBit(x, 1);
return 0;
}
this is a simple way to get the binary form of an int. credit to learncpp.com. im sure this could be used in different ways to get to the same point.
In this approach, the decimal will be converted to the respective binary number in the string formate. The string return type is chosen since it can handle more range of input values.
class Solution {
public:
string ConvertToBinary(int num)
{
vector<int> bin;
string op;
for (int i = 0; num > 0; i++)
{
bin.push_back(num % 2);
num /= 2;
}
reverse(bin.begin(), bin.end());
for (size_t i = 0; i < bin.size(); ++i)
{
op += to_string(bin[i]);
}
return op;
}
};
using bitmask and bitwise and .
string int2bin(int n){
string x;
for(int i=0;i<32;i++){
if(n&1) {x+='1';}
else {x+='0';}
n>>=1;
}
reverse(x.begin(),x.end());
return x;
}
You Could use std::bitset:
#include <bits/stdc++.h>
int main()
{
std::string binary = std::bitset<(int)ceil(log2(10))>(10).to_string(); // decimal number is 10
std::cout << binary << std::endl; // 1010
return 0;
}
SOLUTION 1
Shortest function. Recursive. No headers required.
size_t bin(int i) {return i<2?i:10*bin(i/2)+i%2;}
The simplicity of this function comes at the cost of some limitations. It returns correct values only for arguments between 0 and 1048575 (2 to the power of how many digits the largest unsigned int has, -1). I used the following program to test it:
#include <iostream> // std::cout, std::cin
#include <climits> // ULLONG_MAX
#include <math.h> // pow()
int main()
{
size_t bin(int);
int digits(size_t);
int i = digits(ULLONG_MAX); // maximum digits of the return value of bin()
int iMax = pow(2.0,i)-1; // maximum value of a valid argument of bin()
while(true) {
std::cout << "Decimal: ";
std::cin >> i;
if (i<0 or i>iMax) {
std::cout << "\nB Integer out of range, 12:1";
return 0;
}
std::cout << "Binary: " << bin(i) << "\n\n";
}
return 0;
}
size_t bin(int i) {return i<2?i:10*bin(i/2)+i%2;}
int digits(size_t i) {return i<10?1:digits(i/10)+1;}
SOLUTION 2
Short. Recursive. Some headers required.
std::string bin(size_t i){return !i?"0":i==1?"1":bin(i/2)+(i%2?'1':'0');}
This function can return the binary representation of the largest integers as a string. I used the following program to test it:
#include <string> // std::string
#include <iostream> // std::cout, std::cin
int main()
{
std::string s, bin(size_t);
size_t i, x;
std::cout << "Enter exit code: "; // Used to exit the program.
std::cin >> x;
while(i!=x) {
std::cout << "\nDecimal: ";
std::cin >> i;
std::cout << "Binary: " << bin(i) << "\n";
}
return 0;
}
std::string bin(size_t i){return !i?"0":i==1?"1":bin(i/2)+(i%2?'1':'0');}
I came across one of the common interview question which was to find the closest palindrome number. Say if the input is 127 then output will be 131 and if it is 125 then it should give 121 as output.
I can come up with the logic but my logic fails on certain cases like 91, 911. In these inputs it give 99 , 919 but the correct output is 88 and 909.
Algorithm steps are:
Convert the number into string.
copy first half to second half in reverse order
convert to number and measure the abs. difference with original number diff1
add 1 to half string and now copy first half to second half in reverse order
convert to number and measure the abs. difference with original number diff2
if diff1 is less than diff2 return first number else return second number
This is actually an interesting problem. Obviously what you want to do to make this more than just a brute force is to use the most significant digits and put them in the least significant digit locations to form a palindrome. (I'm going to refer to the difference between the palindrome and the original as the "distance")
From that I'm going to say that we can ignore the least significant half of the numbers because it really doesn't matter (it matters when determining the distance, but that's all).
I'm going to take an abstract number: ABCDEF. Where A,B,C,D,E,F are all random digits. Again as I said D,E,F are not needed for determining the palindrome as what we want is to mirror the first half of the digits onto the second half. Obviously we don't want to do it the other way around or we'd be modifying more significant digits resulting in a greater distance from the original.
So a palindrome would be ABCCBA, however as you've already stated this doesn't always you the shortest distance. However the "solution" is still of the form XYZZYX so if we think about minimizing the "significance" of the digits we're modifying that would mean we'd want to modify C (or the middle most digit).
Lets take a step back and look at why: ABCCBA
At first it might be tempting to modify A because it's in the least significant position: the far right. However in order to modify the least significant we need to modify the most significant. So A is out.
The same can be said for B, so C ends up being our digit of choice.
Okay so now that we've worked out that we want to modify C to get our potentially closer number we need to think about bounds. ABCDEF is our original number, and if ABCCBA isn't the closest palindrome, then what could be? Based on our little detour above we can find it by modifying C. So there are two cases, ABCDEF is greater than ABCCBA or that is less than ABCCBA.
If ABCDEF is greater than ABCCBA then lets add 1 to C. We'll say T = C+1 so now we have a number ABTTBA. So we'll test to make sure that ABCDEF - ABCCBA > ABCDEF - ABTTBA
and if so we know that ABTTBA is the nearest palindrome. As any more modifications to C would just take us more and more distant.
Alternately if ABCDEF is less than ABCCBA then we'll subtract 1 from C. Let's say V = C-1. So we have ABVVBA, which just like above we'll test: ABCDEF - ABCCBA > ABCDEF - ABVVBA and you'll have the same solution.
The trick is that ABCDEF is always between ABTTBA and ABVVBA and the only other palindrome between those numbers is ABCCBA. So you only have 3 options for a solution. and if you compare ABCDEF to ABCCBA you only need to check 2.
I don't think it will be hard for you to adapt this to numbers of any size. and in the case of an odd number of digits you'd simply have ABCBA, ABVBA and ABTBA and so on...
So just like your examples: lets take 911.
Ignore the last 1 we only take the first half (round up). so 91X.
Replace X with 9. we have 919. this is out mid point.
We know our original 911 is less than 919 so subtract 1 from our middle number so we get our second (lower bound) 909.
Compare 911 - 919 and 911 - 909
return the one with the smallest difference.
So this gives us a constant time algorithm :)
As pointed out in the comments this is not constant time in the worst case (oops), but is certainly better than a brute force approach.
This appears to be what you have, but I thought I'd elaborate to hopefully shed light on the issue as it seems to be a small programming error on your part otherwise.
This is an implementation of Naveen's and Don's algorithm. It uses Happy Yellow Face's algorithm as a test oracle.
I would be happy to see people tweak it to remove redundant steps or special cases.
gcc 4.7.3: g++ -Wall -Wextra -std=c++0x nearest-palindrome.cpp
#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
// I do not have std::to_string.
template <class T>
std::string to_string(const T& v) {
std::stringstream ss;
ss << v;
return ss.str(); }
// Nor do I have std::stoi. :(
int stoi(const std::string& s) {
std::stringstream ss(s);
int v;
ss >> v;
return v; }
bool isPalindrome(int n) {
const auto s = to_string(n);
return s == std::string(s.rbegin(), s.rend()); }
int specNearestPalindrome(int n) {
assert(0 <= n);
int less = n, more = n;
while (true) {
if (isPalindrome(less)) { return less; }
if (isPalindrome(more)) { return more; }
--less; ++more; } }
std::string reflect(std::string& str, int n) {
std::string s(str);
s.resize(s.size() + n);
std::reverse_copy(std::begin(str),
std::next(std::begin(str), n),
std::next(std::begin(s), str.size()));
return s; }
bool isPow10(int n) {
return n < 10 ? n == 1 : (n % 10 == 0) && isPow10(n / 10); }
int nearestPalindrome(int n) {
assert(0 <= n);
if (n != 1 && isPow10(n)) { return n - 1; } // special case
auto nstr = to_string(n);
// first half, rounding up
auto f1 = nstr.substr(0, (nstr.size() + 1) / 2);
auto p1 = stoi(reflect(f1, nstr.size() / 2));
const auto twiddle = p1 <= n ? 1 : -1;
auto f2 = to_string((stoi(f1) + twiddle));
auto p2 = stoi(reflect(f2, nstr.size() / 2));
if (p2 < p1) { std::swap(p1, p2); }
return n - p1 <= p2 - n ? p1 : p2; }
int main() {
std::vector<int> tests = { 0, 1, 6, 9, 10, 11, 12, 71, 74, 79, 99, 100, 999, 1000, 9900, 9999, 999000 };
for (const auto& t : tests) {
std::cout <<
(nearestPalindrome(t) == specNearestPalindrome(t) ? "." : "X");
}
std::cout << std::endl;
return 0; }
Here is a generic algorithm that would work1, although using brute-force:
int findNearestPalindrome(int n) {
int less = n;
int more = n;
while(true) {
if (isPalindrome(less)) return less;
if (isPalindrome(more)) return more;
--less;
++more;
}
}
WithinisPalindrome() function, all you need to do is convert the number to a string, and then compare the string with itself reversed.
1 However, this wouldn't check for tie cases, like Ted Hopp commented. You'd have to make a few changes to make it tie-recognizable.
#include <iostream>
#include <cmath>
#include <functional>
#include <limits>
#include <sstream>
// for convience
using namespace std;
using ULL = unsigned long long int;
// calculate the number of digits
auto Len = [](auto num) -> ULL {
return floor(log10(num)) + 1; };
// extract left half of number
auto Halfn = [](auto num, auto olen) {
for (unsigned i = 0; i < olen / 2; num /= 10, ++i);
return num;
};
int main() {
ULL num; cin >> num;
// some basic checking
if (num < 10) {
cerr << "Error, enter a number >= 10";
return 0;
}
if (numeric_limits<ULL>::max() < num) {
cerr << "Error, number too large\n";
return 0;
}
cout << ([](auto num) {
auto olen = Len(num);
auto lhalf = Halfn(num, olen);
function<ULL(ULL)> palin = [olen] (auto lhalf) {
auto half = to_string(lhalf);
// this is the mirror string that needs to be
// appended to left half to form the final
// palindrome
auto tmp = half.substr(0, olen / 2);
// take care of a corner case which
// happens when the number of digits in
// the left half of number decrease, while
// trying to find a lower palindrome
// e.g. num = 100000
// left half = 100 , the value passed to the
// function palin, is 99. if all digits are 9
// then we need to adjust the count of 9,
// otherwise if i simply replicate it, i'll get
// 9999 but one more 9 is required for the
// correct output.
if (olen / 2 > tmp.size() &&
all_of(tmp.begin(), tmp.end(),
[](auto c) { return '9' == c; })) {
tmp += '9';
}
// append, convert and return
half = half + string(tmp.crbegin(),
tmp.crend());
return stoull(half);
};
auto bpalin = palin(lhalf);
auto hpalin = palin(lhalf + 1);
auto lpalin = palin(lhalf - 1);
stringstream ss;
ss << "base palindrome = " << bpalin <<'\n';
ss << "higher palindrome = "<<hpalin <<'\n';
ss << "lower palindrome = " << lpalin <<'\n';
// calculating absolute difference for
// finding the nearest palindrome
auto diffb = labs(bpalin - num);
auto diffh = labs(hpalin - num);
auto diffl = labs(lpalin - num);
auto nearest = (diffb < diffh) ?
(diffb < diffl) ? bpalin : lpalin :
(diffh < diffl) ? hpalin : lpalin;
ss << "nearest palindrome = "
<< nearest << endl;
return move(ss.str());
}(num));
} // end main
class Solution {
public String nearestPalindromic(String n) {
int order = (int) Math.pow(10, n.length()/2);
Long ans = Long.valueOf(new String(n));
Long noChange = mirror(ans);
Long larger = mirror((ans/order)*order + order+1);
Long smaller = mirror((ans/order)*order - 1 );
if ( noChange > ans) {
larger = (long) Math.min(noChange, larger);
} else if ( noChange < ans) {
smaller = (long) Math.max(noChange, smaller);
}
return String.valueOf( ans - smaller <= larger - ans ? smaller :larger) ;
}
Long mirror(Long ans) {
char[] a = String.valueOf(ans).toCharArray();
int i = 0;
int j = a.length-1;
while (i < j) {
a[j--] = a[i++];
}
return Long.valueOf(new String(a));
}
}
Javascript Solution:
const findNearestPalindrome = n => {
if (!n) return 0;
let lowestPalindorm = lowestPalindromeHelper(n);
let largestPalindrome = largestPalindromeHelper(n);
let closestPalindrome = 0;
closestPalindrome =
Math.floor(n - lowestPalindorm) > Math.floor(largestPalindrome - n)
? largestPalindrome
: lowestPalindorm;
console.log(closestPalindrome);
};
//lowestPalindrome check
const lowestPalindromeHelper = num => {
for (let i = num - 1; i >= 0; i--) {
if (isPalindrome(i.toString())) {
return i;
}
}
};
//largest Palindrome Check
const largestPalindromeHelper = num => {
for (let i = num + 1; i <= Number.MAX_SAFE_INTEGER; i++) {
if (isPalindrome(i.toString())) {
return i;
}
}
};
const isPalindrome = n => {
return (
n ===
n
.split('')
.reverse()
.join('')
);
};
findNearestPalindrome(1234);
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 ;
}