Extract Digits From An Integer Without sprintf() Or Modulo - c++

The requirements of this are somewhat restrictive because of the machinery this will eventually be implemented on (a GPU).
I have an unsigned integer, and I am trying to extract each individual digit.
If I were doing this in C++ on normal hardware & performance weren't a major issue, I might do it like this:
(Don't hate on me for this code, it's just a sample to illustrate the method)
#define _CRT_SECURE_NO_WARNINGS
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int someVal = 1234;
char stringVal[256] ={0};
sprintf(stringVal, "%016d", someVal);
int digits[16] = {0};
for( int i = 0; i < strlen(stringVal); ++i )
{
digits[i] = stringVal[i] - '0';
}
cout << "Integer Value = " << someVal << endl;
cout << "Extracted Digits = ";
copy( &digits[0], &digits[16], ostream_iterator<int>(cout, "-") );
cout << endl;
return 0;
}
I'm trying to find a method to extract these digits with the following restrictions:
Don't convert the integer to a string
Don't use the modulus operator (floating point division is fine)
The value in question is a 32-bit unsigned integer
I'm looking for an algorithm, not necessarily specific code. But specific code would be great. The languages I'm most familiar with that translate well to my target hardware are C++, C and assembler.
Any ideas?
EDIT: Here's an update with the algorithm I implemented based on the comments & links below. Thanks all.
#define _CRT_SECURE_NO_WARNINGS
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
unsigned someVal = 12345678;
static const unsigned numDigits = 10;
unsigned digits[numDigits] = {0};
for( unsigned i = 0, temp = someVal; i < numDigits; ++i, temp /= 10 )
{
digits[numDigits-i-1] = temp - 10 * (temp/10) /*temp % 10*/;
}
cout << "Integer Value = " << someVal << endl;
cout << "Extracted Digits = ";
copy( &digits[0], &digits[numDigits], ostream_iterator<int>(cout, "-") );
cout << endl;
return 0;
}

Remember that the modulo operator can actually be implemented as:
mod(a, n) = a - n * floor(a / n)
Hence, you can use your favorite modulo based algorithm. You can simulate floor itself by typecasting.

Have a look around here in Bob Stout's snippets here under the C Archive, and here under the C++ Archive. Not alone that the snippets archive strive to be portable.
Hope this helps,
Best regards,
Tom.

One worth considering, by Terje Mathisen.

Related

Declaring sqrt(var) as a compile time constant in c++

I have a c++ program where I need to pass the square root of a number in a for loop.
#include<random>
#include<iostream>
#include<algorithm>
#include<string>
#include<math.h>
#include <stdlib.h>
#include <windows.h>
#include <ctype.h>
#include <omp.h>
using namespace std;
int main()
{
vector<int>inputDataBits(49); // vector of randomly generated input data bits
#ifdef printDebug
std::cout << "the input data bits are" << endl;
std::cout << "-------------------------" << endl << endl;
int var =49;
const int r=(int)sqrt(var);
float input2d[r][r];
for (int i = 0; i < r; i++)
{
for (int j = 0; j < r; j++)
{
input2d[i][j] = inputDataBits[(j %r) + (i *r)];
std::cout << input2d[i][j] << "\t";
}
std::cout << endl << endl;
}
std::cout << endl << endl;
#endif
return 0;
}
I get an error 'expression must have a constant value'. Is there a way to do this in c++?
This is the purpose of the constexpr keyword (make the value known at compile time).
constexpr int var=49;
constexpr int r=(int)sqrt(var);
Unfortunately, in the documentation sqrt() is not declared as a constexpr function.
Only gcc seems to consider it as constexpr but it is not portable.
The size of an array needs to be known at compile-time.
Instead you can use a std::vector, which has a dynamic size.
std::vector<std::vector<float>> input2d(std::vector<float>(r), r);

Generate random letter array and count occurences

Hello I am trying to generate a random array of the length that the user inputs. My array should then print and display the occurences of those letters in the array. So far this only prints up to the letter g and the occurences are incorrect. If someone could tell me what I am doing wrong it would help alot. Thank you.
#include <iostream>
#include <cstring>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
srand(time(0));
int i, num;
char ch;
char chars[]={'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'};
int freq[26]={0};
cout << "How many letters do you want in your string? ";
cin >> num;
for (i=0; i < num; i++)
{
ch = chars[rand()%26];
chars[i]=ch;
freq[i] +=1;
cout << ch;
}
for (char lower = 'a'; lower <='z'; lower++)
{
cout << "\nLetter" << lower << "is " << freq[lower] << "times";
}
}
Problem 1
The lines
chars[i]=ch;
freq[i] +=1;
are not right. You need to use:
int index = ch - 'a';
freq[index] += 1;
Problem 2
The index in the for loop for printing the data is not correct either.
You need to use:
for (char lower = 'a'; lower <='z'; lower++)
{
int index = lower - 'a';
cout << "\nLetter" << lower << "is " << freq[index] << "times";
}
Important Note
It is worth noting that the C++ standard does not guarantee that lower case letters are contiguous. (Thanks #MartinBonner). For instance, if your system uses EBCDIC encoding your program won't work.
To make your code robust, it will be better to use a std::map.
int main()
{
srand(time(0));
int i, num;
char ch;
char chars[]={'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'};
std::map<char, int> freq;
// Initialize freq.
for ( ch : chars )
{
freq[ch] = 0;
}
cout << "How many letters do you want in your string? ";
cin >> num;
for (i=0; i < num; i++)
{
ch = chars[rand()%26];
freq[ch] +=1;
}
for (auto item : freq )
{
cout << "\nLetter" << item.first << "is " << item.second << "times";
}
}
You might wanna give a look to C++11 Pseudo-random number generation here is a short way of generating the range that you want using this:
#include <algorithm>
#include <array>
#include <random>
#include <vector>
using namespace std;
int main()
{
int arraySize = 35;
mt19937 engine{random_device{}()};
uniform_int_distribution<> dist{'a', 'z'};
vector<char> vec;
generate_n(back_inserter(vec), arraySize, [&]() { return static_cast<char>(dist(engine); }));
//To count occurrences
array<int, 26> freq;
for (auto c : vec) { ++freq[c-'a']; }
return 0;
}
You should not write into chars, and freq should be extended to cover the a...z range (the ASCII codes), which it does not. Also, increase at index ch, not at i.
I do not even know that range from the top of my head, but it could be modified to track all possible bytes instead (0...255), see result on https://ideone.com/xPGls7
List of changes:
int freq[256]={0}; // instead of int freq[26]={0};
// chars[i]=ch; is removed
freq[ch] +=1; // instead of freq[i] +=1;
Then it works.
Using lambda functions to do most of the work.
#include <algorithm>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <ostream>
#include <random>
#include <string>
#include <utility>
#include <vector>
using namespace std::string_literals;
int main()
{
std::mt19937::result_type seed = std::random_device{}();
auto engine = std::mt19937(seed);
auto dist = std::uniform_int_distribution<>('a', 'z');
auto random_letter = [&engine, &dist]() { return static_cast<char>(dist(engine)); };
std::cout << "How many letters do you want to generate? "s;
int n;
if (!(std::cin >> n)) { return EXIT_FAILURE; }
auto letters = std::vector<char>();
std::generate_n(std::back_inserter(letters), n, random_letter);
auto zero = std::map<char, int>();
auto const frequencies = std::accumulate(std::cbegin(letters), std::cend(letters), zero,
[](auto& acc, auto c)
{
++acc[c];
return acc;
});
for (auto const [c, freq] : frequencies)
{
std::cout << "The letter '"s << c << "' appeared "s << freq << " times." << std::endl;
}
return 0;
}

How to print a number with precision given by the user in c++

How to print a number with precision given by the user. And how to print precision after decimal point up to 100 digits.
Suppose A,B,C be three numbers and take the value of three numbers from the user and I have to print the answer of A/B ( A divided by B ) to C floating points.
If A=22, B=7 , C=25, that means I have to print the result of 22/7 to 25 floating points.
3.1428571428571428571428571 , this is the answer of 22/7 , 25 digits after decimal point.
As many have pointed out, use std::fixed and std::setprecision
#include <iostream>
#include <iomanip>
int main()
{
float x = 22.0/7.0;
std::cout << std::fixed << std::setprecision(25) << x;
return 0;
}
But when you run this you will see the output is
3.1428570747375488281250000 when it should be
3.1428571428571428571428571. What gives?
Well, floats can only hold so much before having to give up and say, "Best I can do, mate." Rumour has it, this point is about 7 digits. Based on a quick count that looks about right.
So what say we try a double. They're twice the size!
#include <iostream>
#include <iomanip>
int main()
{
double x = 22.0/7.0;
std::cout << std::fixed << std::setprecision(25) << x;
return 0;
}
gives us
3.1428571428571427937015414. Still not
3.1428571428571428571428571, but closer. What have we got that's bigger than double? Just tried long double. No dice on my computer. Looks like we're going to have to go looking for a good high precision floating point library.
Bummer. Well, there is one in Boost. I someday expect to see boost::kitchen_sink.
To print a float with a precision "n" you should write :
printf("%.nf"); // like printf("%.3f")
there you are a c++ full code
#include <stdio.h>
#include <stdlib.h>
#include <strstream>
#include <iostream>
int main()
{
// print a float with precision '4'
printf("%.4f",10.125f);
// print a float with precision 'n'
char * buffer = new char[100];
int n;
std::strstream ss; // like cout but outputs to a string buffer
ss<<"%.";
std::cout<<"Enter precision : ";
std::cin>>n;
ss<<n<<"f";
printf(ss.str(),10,125); // ss.str() to get buffer content
delete[] buffer;
return 0;
}
but very simply you still can write
std::cout << std::setprecision(n) << float_var;
EDIT :
you can do you own division ! i mean you can simulate the devision of the processor and get whatever precision you want , till inifinity ! , there you are the amazing code that i wrote for my friend one time for fun :
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <chrono>
int main()
{
std::cout.sync_with_stdio(false); // accelerate output
register int x,y;
char opp;
std::cout<<"Enter x/y : ";
std::cin>>x>>opp>>y;
std::cout<<"deviding "<<x<<" by "<<y<<std::endl;
register int precision;
std::cout<<"Enter precision : ";
std::cin>>precision;
register int precision_counter = 0;
typedef std::chrono::high_resolution_clock Time;
typedef std::chrono::nanoseconds ms;
typedef std::chrono::duration<float> fsec;
auto t0 = Time::now();
std::cout <<"Result = ";
std::cout<<x/y;
// check if there will be a float point result to print a point
if(x<y || x%y != 0)
{
std::cout<<".";
x%=y; // remove what we printed
register int counter = 0;
// print digts that are after the float point
while (precision_counter<precision )
{
x*=10;
while (x>=y)
{
x-= y;
counter++;
}
std::cout<<counter;
counter = 0;
precision_counter++;
}
/*
optimized loop :
while (precision_counter<precision )
{
x*=10;
std::cout<<x/y;
x%=y;
precision_counter++;
}
**/
}
auto t1 = Time::now();
fsec fs = t1 - t0;
std::cout<<"\n";
ms d = std::chrono::duration_cast<ms>(fs);
std::cout << fs.count() << "s\n";
std::cout << d.count() << " nanosecond\n";
std::cout<<std::endl;
system("pause");
return 0;
}
#include <iostream>
#include <string>
#include <sstream>
std::string f(int A, int B, int C){//A: numerator, B:denominator, C:digits after decimal point
std::stringstream ss;
int count = 0;
if(A < 0){
A = -A;
++count;
}
if(B < 0){
B = -B;
++count;
}
if(count == 1)
ss << '-';
ss << A / B << '.';
A %= B;
A *= 10;
count = C;
while(count--){
ss << A / B;
A %= B;
A *= 10;
}
return ss.str();
}
int main(void){
std::cout << f(22, 7, 25) << std::endl;
return 0;
}

Setprecision doesn't work during exponentiation with base of 10 in C++

My code should calculate with maximum precision different powers of different ints. Sometimes I have problem digits after nought point.
Example code:
#include <iostream>
#include <math.h>
#include <iomanip>
using namespace std;
int main()
{
cout << setprecision(10000);
int length = 5;
long double Maxi = pow(10, length);
cout << Maxi << endl;
return 0;
}
prints
100000.00000000000000710542735760100185871124267578125
instead of
100000
Screen: http://postimg.org/image/epdsrinkx/
Is it something to worry about or should I just round down and forget about it?

what is the exact time to run a program?

I want the exact time to run a program, I use it from clock(). But there is a problem that I can not give an exact time for small n like 2000.
I want it to return the correct answer for n=1000.
#include <iostream>
#include <ctime>
#include <algorithm>
using namespace std;
#define show_time(x, y) cout << endl << #x << " : " << y << endl;
int main()
{
int n;
cin >> n;
int *a = new int[n];
for(int i=0; i<n; i++)
a[i] = i;
random_shuffle(a, a+n);
int last = clock();
//STL_sort:
sort(a, a+n);
int lastP = clock();
show_time(STL_sort, (double)(lastP-last)/CLOCKS_PER_SEC);
return 0;
}
The output is 0. (Definitely 0 will not be the answer)
What platform are you running on? If you're on Windows, you could try the high-resolution time library.
If you have access to C++11, there is a header called chrono that has similar functionality, and is portable (ish)!