Related
I'm struggling with the bit shifting algorithm for computing the square root of big numbers. I've got arrays of 32bit words and doesn't matter the input, the output is always the same number. Previously the algorithm worked with 1 bit per array cell, but when I switched to words in cells it doesn't work anymore.
I wrote methods that work perfectly separately (adding words, subtracting words, shifting bits to the right) but the whole program doesn't give what I expect.
When the input number has 0 in it's first position, the output is 0, when it has any number but the 1st cell of the array isn't 0, the output is always the same.
The variables:
uint32_t var[4] = {0,0,0,0};
uint32_t w_number[word_len] = {1, 0,0,234324};
uint32_t one[word_len] = {0,0,0,0};
uint32_t var[word_len] = {0,0,0,0};
uint32_t buff[word_len] = {0,0,0,0};
uint32_t result[word_len] = {0,0,0,0};
The code:
one[0] = 1L << 30;
while (isBigger(one, input))
{
shiftR_word(one);
shiftR_word(one);
}
while (!isZero(one))
{
add_word(result, one, var); //the result of one+result is put in Var.
if ((isBigger(input, var) || equals(input, var))) // if (input >= var)
{
subtract_word(input, var, input); // input-=var
shiftR_word(result);
add_word(result, one, result);
}
else
{
shiftR_word(result);
}
shiftR_word(one);
shiftR_word(one);
}
std::cout << "\nOut: ";
printAsBit(result);
std::cout << std::endl;
Here's the shifting algorithm I'm using that may cause the problems.
void shiftR_word(uint32_t w_number[], int n=4)
{
// n - how many words
//(n*32b word) >> 1
bool* odd = new bool[n];
for (int i = 0; i < n; i++)
{
if( w_number[i] & 1 )
odd[i]=true;
else
odd[i]=false;
}
for (int i = 0; i < n; i++)
w_number[i] >>= 1;
for (int i = 0; i <= n-1; i++)
{
if(odd[i])
{
w_number[i+1] = w_number[i+1] | 1 << 31;
}
}
delete[] odd;
}
The add function:
void add_word(uint32_t a[], uint32_t b[], uint32_t result[], int len=4)
{
int carry=0;
for (int i = len-1; i >=0; i--)
{
result[i]=a[i]+b[i]+carry;
carry = (a[i]>result[i] || b[i]>result[i]) ? 1 : 0;
}
}
isBigger method:
bool isBigger(uint32_t a[],uint32_t b[] ,int len=4)
{
for (int i = 0; i < len; i++)
{
if (a[i]>b[i])
{
return true;
}
}
return false;
}
I am unable to spot the error in the code, especially that all of the methods seem to work when I test them separately.
isBigger does not work. If you have (length 2) values of {2, 5} for a and {6, 3} for b it will return true when it should return false. Inside the loop, you want to return false if a[i] < b[i], and only check the next value if the two values are equal.
bool isBigger(const uint32_t a[], const uint32_t b[], int len = 4)
{
for (int i = 0; i < len; i++)
{
if (a[i] > b[i])
return true;
if (a[i] < b[i])
return false;
}
// Only get here if `a` and `b` are equal
return false;
}
Additionally, shiftR_word has Undefined Behavior, because w_number[i+1] can be past the end of the array (when i == n-1, you'll access w_number[n - 1 + 1] or w_number[n]). Your loop condition in this instance should be i < n-1. However, that function is rather inefficient. It can be rewritten to only need one loop and no memory allocation, but that's left as an exercise for the reader.
I want to distribute numbers by a certain percentage randomly within a matrix.For example I have a matrix 150*150 and I want to Fill out with 0,1,2
randomly with percentage like this 10% for 0 30% for 2 and 60% for 1.What should I do.actually I did something but without percentage but it didn't work perfectly.
for (int i = 0; i < 151 i++) {
for (int j = 0; j <151; j++) {
if (random(100) < 10) {
Array(i, j) = 1;
}
if (random(50) < 10) {
Array(i, j) = 2;
}
}
}
Since C++11, the Standard Library provides the function std::discrete_distribution, defined in header <random>, which
produces random integers on the interval [0, n), where the probability of each individual integer i is defined as w
i/S, that is the weight of the ith integer divided by the sum of all n weights.
Given OP's percentages:
std::discrete_distribution<int> d({10, 60, 30});
HERE, a testable code snippet.
I'm quite sure that this is not the most efficient way to approach this problem and my beginner c++ code should never be used as it's, but still if you want a reference, this is how i did it :
#include <iostream>
#include <random>
#include <tuple>
#include <vector>
#define ROWS 5
#define COLS 5
using tuple = std::tuple<int, int>;
const int Percentage(const int value)
{
const int percent = std::round((value / 100.0) * (ROWS * COLS));
std::cout << value << "% of " << ROWS * COLS << " : " << percent << std::endl;
return percent;
}
const int RandomIndex(const int& size)
{
std::mt19937 range;
range.seed(std::random_device()());
std::uniform_int_distribution<std::mt19937::result_type> dist(0, size);
return dist(range);
}
void FillMatrix(int matr[][COLS], std::vector<tuple>& num)
{
// holds the numbers, from which a random number
// will be stored to the matrix
std::vector<int> fillers;
// holds the random index among the fillers
uint8_t random_index;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
/*
* check if the count of a particular number to be added to
* the matrix is zero or not.
* if zero : then dont append to filler vector
* else : append to filler vector
*/
for (tuple item : num) {
if (std::get<1>(item) != 0) {
fillers.emplace_back(std::get<0>(item));
}
}
// get the index of a random item in fillers vector
random_index = RandomIndex(fillers.size() - 1);
// insert this random element to matrix
matr[i][j] = fillers[random_index];
/*
* find the percentage value(or count) of the number
* corresponding to the random number and decrement it
* so as to denote that it has been used.
*/
for (tuple& item : num) {
if (std::get<0>(item) == fillers[random_index]) {
std::get<1>(item) -= 1;
}
}
// clear the current fillers vector
fillers.clear();
}
}
}
int main()
{
int matrix[ROWS][COLS];
// each tuple has a number and it's corresponding percentage
std::vector<tuple> numbers = {tuple(0, Percentage(10)),
tuple(1, Percentage(30)),
tuple(2, Percentage(60))};
// fill the matrix with values provided in the vector
FillMatrix(matrix, numbers);
// print the matrix
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
std::cout << matrix[i][j] << "\t";
}
std::cout << "\n";
}
return 0;
}
define ROWS and COLS as 150 in your case.
I know how to generate all n-digit number in the traditional number way,
for(long long number = pow(10, n-1); number < pow(10, n); number++) {
cout << number << endl;
}
for example,
for n = 5, it will generate 10000 to 99999;
However, since I will have to evaluate each number's digits, it is much convenient to construct the numbers in a digit array format in the first place.
for example, following code generate all 5-digit number in an array way:
for(int i = 1; i < 9; i++)
for(int j = 0; j < 9; j++)
for(int k = 0; k < 9; k++)
for(int l = 0; l < 9; l++)
for(int m = 0; m < 9; m++) {
//executed 9 * 10^4 = 90000 times
//construct my array instance with i, j, k, l, m
cout << i << j << k << l << m << endl;
}
Now the problem is: n is unknown. (for example, it could be 2, 3, 4, 5, 6..., 10)
Then how can I generate n-digit-array based on a number n?
For example, I want a piece of code like follows (any better ways than this one is highly appreciated):
for(int x = 0; x < n; x++) {
//each x is a layer of the loop ?!
.....
}
There is no reason to limit ourselves to the range 0 - 9 for each digit of the number.
For each numerical place, we'll represent a range:
std::pair<int,int> range;
Each loop in your example is iterating from the beginning of the range to the end of the range.
All the loops together are really just a series of ranges; each nested loop being responsible for the next digit of your generated number.
We can represent that, in the following way:
std::vector<std::pair<int, int>> ranges;
If you think about how nested for loops work, you can emulate the same functionality over the vector using two pointers. I've done that and wrapped the functionality into a class:
//header
class Range_Combinator {
public:
Range_Combinator(std::vector<std::pair<int, int>> const &ranges_in);
std::vector<int> Next();
std::vector<int> Current();
bool Done();
private:
bool Adjust();
void Reset_From_Current_Back(int from);
std::vector<std::pair<int, int>> ranges;
int current;
int last;
bool all_exausted;
std::vector<int> current_vals;
};
//source
Range_Combinator::Range_Combinator(
std::vector<std::pair<int, int>> const &ranges_in) {
ranges = ranges_in;
last = ranges.size() - 1;
current = last;
all_exausted = false;
for (auto it : ranges) {
current_vals.push_back(it.first);
}
}
std::vector<int> Range_Combinator::Next() {
all_exausted = Adjust();
return current_vals;
}
std::vector<int> Range_Combinator::Current() { return current_vals; }
bool Range_Combinator::Done() { return all_exausted; }
bool Range_Combinator::Adjust() {
if (current_vals[current] < ranges[current].second) {
current_vals[current]++;
} else {
while (current_vals[current] == ranges[current].second) {
current--;
}
if (current < 0) {
return true;
}
Reset_From_Current_Back(current + 1);
current_vals[current]++;
current = last;
}
return false;
}
void Range_Combinator::Reset_From_Current_Back(int from) {
for (int i = from; i <= last; ++i) {
current_vals[i] = ranges[i].first;
}
}
This is how you would use it:
//create range combinator
std::vector<std::pair<int,int>> ranges{{1,2},{3,4}};
Range_Combinator r(ranges);
//print each number
auto number = r.Current();
while (!r.Done()){
for (auto it: number) std::cout << it; std::cout << '\n';
number = r.Next();
}
//prints: 13
// 14
// 23
// 24
I don't know why you need that but you can try this:
size_t n = ; //whatever value
unsigned char* x = new unsigned char[n]();
x[0] = 1; //make it n-digit 10000...000
do
{
//process digits here
++x[n - 1];
for (size_t i = n; i > 1; --i)
{
if (x[i - 1] == 10)
{
x[i - 1] = 0;
++x[i - 2];
}
}
} while (x[0] < 10);
delete [] x;
You can even process not decimal numbers, just replace hard-coded 10 into appropriate number.
I suppose I could just write out the whole thing for you, but that would be no fun. Instead, I'll just outline the basic approach, and you can finish the answer yourself by filling in the blanks.
Consider an n-digit long number being represented this way:
struct digit {
struct digit *next;
int n; /* Digit 0-9 */
};
A single number represented, in this manner, can be printed out this way:
void print_digit(struct digit *p)
{
while (p)
{
std::cout << p->n;
p=p->next;
}
std::cout << std::endl;
}
Now, let's create a recursive loop, that iterates over all possible n-digit numbers:
void iterate(int ndigits)
{
for (int i=0; i<10; ++i)
{
if (ndigits > 1)
{
iterate(ndigits-1);
}
else
{ // This is the last digit
// Here be dragons
}
}
}
After a bit of thinking, you can see that if, for example, you call iterate(4), then when the "hear be dragons" part gets executed, this will be inside a four-deep nested iteration stack. There will be four level-deep for loops, nested within each other. And, with iterate(6), there will be six of them, and so on.
Now, consider the fact that the struct digit-based representation of n-digit numbers is also a stack, of sorts.
Therefore, the homework assignment here would be to use this recursive iteration to dynamically construct this linked list, on the stack, with the "here be dragons" part simply invoking print_digit() in order to print each number.
Hint: iterate() will need to have a few more parameters, that it will use appropriately, with a certain preset value for them, on the initial call to iterate().
A simple way without thinking of efficiency:
#include <cstdio>
int main(void) {
int n = 3; // the number of digits
long long start = 1;
int *array = new int[n];
for (int i = 1; i < n; i++) start *= 10;
for(long long x = start; x < start * 10; x++) { // not all 10-digit number will fit in 32-bit integer
// get each digits in decimal, lowest digit in array[0]
for (int i = 0, shift = 1; i < n; i++, shift *= 10) array[i] = (int)((x / shift) % 10);
// do some work with it (print it here)
for (int i = n - 1; i >= 0; i--) printf("%d", array[i]);
putchar('\n');
}
delete[] array;
return 0;
}
I've looked up some websites but I couldn't find an answer to my problem.
Here's my code:
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <time.h>
#include<iomanip>
#include<array>
#include <algorithm>
using namespace std;
const int AS = 6;
int filling(void);
void printing(int[AS][AS]);
int forsorting(int[][AS], int);
int main()
{
int funny = 0;
int timpa = 0;
int counter = 0;
int Array[AS][AS];
srand(time(0));
for (int i = 0; i<AS; i++)
{
for (int j = 0; j<AS; j++)
Array[i][j] = filling();
}
cout << "The unsorted array is" << endl << endl;
printing(Array);
cout << "The sorted array is" << endl << endl;
for (int il = 0; il<AS; il++)
{
for (int elle = 0; elle<AS; elle++)
Array[il][elle] =forsorting(Array, funny);
printing(Array);
}
system("PAUSE");
return 0;
}
int filling(void)
{
int kira;
kira = rand() % 87 + 12;
return kira;
}
void printing(int Array[AS][AS])
{
int counter = 0;
for (int i = 0; i<AS; i++)
{
for (int j = 0; j<AS; j++)
{
cout << setw(5) << Array[i][j];
counter++;
if (counter%AS == 0)
cout << endl << endl;
}
}
}
int forsorting(int Array[AS][AS], int funny)
{
int c, tmp, x;
int dice = 0;
int Brray[AS*AS];
int timpa = 0;
int super = 0;
//Transofrming Array[][] into Brray[]
for (int i = 0; i < AS; i++)
{
for (int k = 0; k < AS; k++)
{
Brray[timpa] = Array[i][k];
timpa++;
}
}
//Bubble sorting in Brray[]
for (int passer = 1; passer <= AS-1; passer++)
{
for (int timon = 1; timon <= AS-1; timon++)
{
if (Brray[timpa]>Brray[timpa + 1])
{
super = Brray[timpa];
Brray[timpa] = Brray[timpa + 1];
Brray[timpa + 1] = super;
}
}
}
//Transforming Brray[] into Array[][]
for (int e = 0; e<AS; e++)
{
for (int d = 0; d<AS; d++)
{
Brray[dice] = Array[e][d];
dice++;
}
}
***There's a part missing here***
}
What I have to do is, write a program using 3 functions.
The 1st function would fill my 2D array randomly (no problem with this part)
the 2nd function would print the unsorted array on the screen (no problem with this part)
and the 3rd function would sort my array diagonally as shown in this picture:
Then I need to call the 2nd function to print the sorted array. My problem is with the 3rd function I turned my 2D array into a 1D array and sorted it using Bubble sorting, but what I can't do is turn it back into a 2D array diagonaly sorted.
If you can convert from a 2D array to a 1D array, then converting back is the reverse process. Take the same loop and change around the assignment.
However in your case the conversion itself is wrong. It should take indexes in the order (0;0), (0;1), (1;0). But what it does is take indexes in the order (0;0), (0;1), (1;1).
My suggestion is to use the fact that the sum of the X and Y coordinates on each diagonal is the same and it goes from 0 to AS*2-2.
Then with another loop you can check for all possible valid x/y combinations. Something like this:
for ( int sum = 0; sum < AS*2-1; sum++ )
{
for ( int y = sum >= AS ? sum-AS+1 : 0; y < AS; y++ )
{
x = sum - y;
// Here assign either from Array to Brray or from Brray to Array
}
}
P.S. If you want to be really clever, I'm pretty sure that you can make a mathematical (non-iterative) function that converts from the index in Brray to an index-pair in Array, and vice-versa. Then you can apply the bubble-sort in place. But that's a bit more tricky than I'm willing to figure out right now. You might get extra credit for that though.
P.P.S. Realization next morning: you can use this approach to implement the bubble sort directly in the 2D array. No need for copying. Think of it this way: If you know a pair of (x;y) coordinates, you can easily figure out the next (x;y) coordinate on the list. So you can move forwards through the array from any point. That is all the the bubble sort needs anyway.
Suppose you have a 0-based 1-dimensional array A of n = m^2 elements. I'm going to tell you how to get an index into A, given and a pair of indices into a 2D array, according to your diagonalization method. I'll call i the (0-based) index in A, and x and y the (0-based) indices in the 2D array.
First, let's suppose we know x and y. All of the entries in the diagonal containing (x,y) have the same sum of their coordinates. Let sum = x + y. Before you got to the diagonal containing this entry, you iterated through sum earlier diagonals (check that this is right, due to zero-based indexing). The diagonal having sum k has a total of k + 1 entries. So, before getting to this diagonal, you iterated through 1 + 2 + ... + (sum - 1) entries. There is a formula for a sum of the form 1 + 2 + ... + N, namely N * (N + 1) / 2. So, before getting to this diagonal, you iterated through (sum - 1) * sum / 2 entries.
Now, before getting to the entry at (x,y), you went through a few entries in this very diagonal, didn't you? How many? Why, it's exactly y! You start at the top entry and go down one at a time. So, the entry at (x,y) is the ((sum - 1) * sum / 2 + y + 1)th entry, but the array is zero-based too, so we need to subtract one. So, we get the formula:
i = (sum - 1) * sum / 2 + y = (x + y - 1) * (x + y) / 2 + y
To go backward, we want to start with i, and figure out the (x,y) pair in the 2D array where the element A[i] goes. Because we are solving for two variables (x and y) starting with one (just i) and a constraint, it is trickier to write down a closed formula. In fact I'm not convinced that a closed form is possible, and certainly not without some floors, etc. I began trying to find one and gave up! Good luck!
It's probably correct and easier to just generate the (x,y) pairs iteratively as you increment i, keeping in mind that the sums of coordinate pairs are constant within one of your diagonals.
Store the "diagonally sorted" numbers into an array and use this to display your sorted array. For ease, assume 0-based indexing:
char order[] = { 0, 1, 3, 6, 10, 2, 4, 7, 11, 15, .. (etc)
Then loop over this array and display as
printf ("%d", Array[order[x]]);
Note that it is easier if your sorted Array is still one-dimensional at this step. You'd add the second dimension only when printing.
Following may help you:
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <vector>
template<typename T>
class DiagArray
{
public:
DiagArray(int size) : width(size), data(size * size), orders(size * size)
{
buildTableOrder(size);
}
const T& operator() (int x, int y) const { return data[orders[width * y + x]]; }
T& operator() (int x, int y) { return data[orders[width * y + x]]; }
void sort() { std::sort(data.begin(), data.end()); }
void display() const {
int counter = 0;
for (auto index : orders) {
std::cout << std::setw(5) << data[index];
counter++;
if (counter % width == 0) {
std::cout << std::endl;
}
}
}
private:
void buildTableOrder(int size)
{
int diag = 0;
int x = 0;
int y = 0;
for (int i = 0; i != size * size; ++i) {
orders[y * size + x] = i;
++y;
--x;
if (x < 0 || y >= size) {
++diag;
x = std::min(diag, size - 1);
y = diag - x;
}
}
}
private:
int width;
std::vector<T> data;
std::vector<int> orders;
};
int main(int argc, char *argv[])
{
const int size = 5;
DiagArray<int> da(size);
for (int y = 0; y != size; ++y) {
for (int x = 0; x != size; ++x) {
da(x, y) = size * y + x;
}
}
da.display();
std::cout << std::endl;
da.sort();
da.display();
return 0;
}
Thank you for your assistance everyone, what you said was very useful to me. I actually was able to think about clearly and came up with a way to start filling the array based on your recommendation, but one problem now, Im pretty sure that my logic is 99% right but there's a flaw somewhere. After I run my code the 2nd array isnt printed on the screen. Any help with this?
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <time.h>
#include<iomanip>
#include<array>
#include <algorithm>
using namespace std;
const int AS = 5;
int filling(void);
void printing(int[AS][AS]);
int forsorting(int[][AS], int);
int main()
{
int funny = 0;
int timpa = 0;
int counter = 0;
int Array[AS][AS];
srand(time(0));
for (int i = 0; i<AS; i++)
{
for (int j = 0; j<AS; j++)
Array[i][j] = filling();
}
cout << "The unsorted array is" << endl << endl;
printing(Array);
cout << "The sorted array is" << endl << endl;
for (int il = 0; il<AS; il++)
{
for (int elle = 0; elle<AS; elle++)
Array[il][elle] =forsorting(Array, funny);
}
printing(Array);
system("PAUSE");
return 0;
}
int filling(void)
{
int kira;
kira = rand() % 87 + 12;
return kira;
}
void printing(int Array[AS][AS])
{
int counter = 0;
for (int i = 0; i<AS; i++)
{
for (int j = 0; j<AS; j++)
{
cout << setw(5) << Array[i][j];
counter++;
if (counter%AS == 0)
cout << endl << endl;
}
}
}
int forsorting(int Array[AS][AS], int funny)
{int n;
int real;
int dice = 0;
int Brray[AS*AS];
int timpa = 0;
int super = 0;
int median;
int row=0;
int col=AS-1;
//Transofrming Array[][] into Brray[]
for (int i = 0; i < AS; i++)
{
for (int k = 0; k < AS; k++)
{
Brray[timpa] = Array[i][k];
timpa++;
}
}
//Bubble sorting in Brray[]
for (int passer = 1; passer <= AS-1; passer++)
{
for (int timon = 1; timon <= AS-1; timon++)
{
if (Brray[timpa]>Brray[timpa + 1])
{
super = Brray[timpa];
Brray[timpa] = Brray[timpa + 1];
Brray[timpa + 1] = super;
}
}
}
//Transforming Brray[] into sorted Array[][]
for(int e=4;e>=0;e--)//e is the index of the diagonal we're working in
{
if(AS%2==0)
{median=0.5*(Brray[AS*AS/2]+Brray[AS*AS/2-1]);
//We start filling at median - Brray[AS*AS/2-1]
while(row<5 && col>=0)
{real=median-Brray[AS*AS/2-1];
Array[row][col]=Brray[real];
real++;
col--;
row++;}
}
else {
median=Brray[AS*AS/2];
//We start filling at Brray[AS*AS/2-AS/2]
while(row<5 && col>=0)
{real=Brray[AS*AS/2-AS/2];
n=Array[row][col]=Brray[real];
real++;
col--;
row++;}
}
}
return n;
}
Thanks again for your assistance
I am currently reading "Programming: Principles and Practice Using C++", in Chapter 4 there is an exercise in which:
I need to make a program to calculate prime numbers between 1 and 100 using the Sieve of Eratosthenes algorithm.
This is the program I came up with:
#include <vector>
#include <iostream>
using namespace std;
//finds prime numbers using Sieve of Eratosthenes algorithm
vector<int> calc_primes(const int max);
int main()
{
const int max = 100;
vector<int> primes = calc_primes(max);
for(int i = 0; i < primes.size(); i++)
{
if(primes[i] != 0)
cout<<primes[i]<<endl;
}
return 0;
}
vector<int> calc_primes(const int max)
{
vector<int> primes;
for(int i = 2; i < max; i++)
{
primes.push_back(i);
}
for(int i = 0; i < primes.size(); i++)
{
if(!(primes[i] % 2) && primes[i] != 2)
primes[i] = 0;
else if(!(primes[i] % 3) && primes[i] != 3)
primes[i]= 0;
else if(!(primes[i] % 5) && primes[i] != 5)
primes[i]= 0;
else if(!(primes[i] % 7) && primes[i] != 7)
primes[i]= 0;
}
return primes;
}
Not the best or fastest, but I am still early in the book and don't know much about C++.
Now the problem, until max is not bigger than 500 all the values print on the console, if max > 500 not everything gets printed.
Am I doing something wrong?
P.S.: Also any constructive criticism would be greatly appreciated.
I have no idea why you're not getting all the output, as it looks like you should get everything. What output are you missing?
The sieve is implemented wrongly. Something like
vector<int> sieve;
vector<int> primes;
for (int i = 1; i < max + 1; ++i)
sieve.push_back(i); // you'll learn more efficient ways to handle this later
sieve[0]=0;
for (int i = 2; i < max + 1; ++i) { // there are lots of brace styles, this is mine
if (sieve[i-1] != 0) {
primes.push_back(sieve[i-1]);
for (int j = 2 * sieve[i-1]; j < max + 1; j += sieve[i-1]) {
sieve[j-1] = 0;
}
}
}
would implement the sieve. (Code above written off the top of my head; not guaranteed to work or even compile. I don't think it's got anything not covered by the end of chapter 4.)
Return primes as usual, and print out the entire contents.
Think of the sieve as a set.
Go through the set in order. For each value in thesive remove all numbers that are divisable by it.
#include <set>
#include <algorithm>
#include <iterator>
#include <iostream>
typedef std::set<int> Sieve;
int main()
{
static int const max = 100;
Sieve sieve;
for(int loop=2;loop < max;++loop)
{
sieve.insert(loop);
}
// A set is ordered.
// So going from beginning to end will give all the values in order.
for(Sieve::iterator loop = sieve.begin();loop != sieve.end();++loop)
{
// prime is the next item in the set
// It has not been deleted so it must be prime.
int prime = *loop;
// deleter will iterate over all the items from
// here to the end of the sieve and remove any
// that are divisable be this prime.
Sieve::iterator deleter = loop;
++deleter;
while(deleter != sieve.end())
{
if (((*deleter) % prime) == 0)
{
// If it is exactly divasable then it is not a prime
// So delete it from the sieve. Note the use of post
// increment here. This increments deleter but returns
// the old value to be used in the erase method.
sieve.erase(deleter++);
}
else
{
// Otherwise just increment the deleter.
++deleter;
}
}
}
// This copies all the values left in the sieve to the output.
// i.e. It prints all the primes.
std::copy(sieve.begin(),sieve.end(),std::ostream_iterator<int>(std::cout,"\n"));
}
From Algorithms and Data Structures:
void runEratosthenesSieve(int upperBound) {
int upperBoundSquareRoot = (int)sqrt((double)upperBound);
bool *isComposite = new bool[upperBound + 1];
memset(isComposite, 0, sizeof(bool) * (upperBound + 1));
for (int m = 2; m <= upperBoundSquareRoot; m++) {
if (!isComposite[m]) {
cout << m << " ";
for (int k = m * m; k <= upperBound; k += m)
isComposite[k] = true;
}
}
for (int m = upperBoundSquareRoot; m <= upperBound; m++)
if (!isComposite[m])
cout << m << " ";
delete [] isComposite;
}
Interestingly, nobody seems to have answered your question about the output problem. I don't see anything in the code that should effect the output depending on the value of max.
For what it's worth, on my Mac, I get all the output. It's wrong of course, since the algorithm isn't correct, but I do get all the output. You don't mention what platform you're running on, which might be useful if you continue to have output problems.
Here's a version of your code, minimally modified to follow the actual Sieve algorithm.
#include <vector>
#include <iostream>
using namespace std;
//finds prime numbers using Sieve of Eratosthenes algorithm
vector<int> calc_primes(const int max);
int main()
{
const int max = 100;
vector<int> primes = calc_primes(max);
for(int i = 0; i < primes.size(); i++)
{
if(primes[i] != 0)
cout<<primes[i]<<endl;
}
return 0;
}
vector<int> calc_primes(const int max)
{
vector<int> primes;
// fill vector with candidates
for(int i = 2; i < max; i++)
{
primes.push_back(i);
}
// for each value in the vector...
for(int i = 0; i < primes.size(); i++)
{
//get the value
int v = primes[i];
if (v!=0) {
//remove all multiples of the value
int x = i+v;
while(x < primes.size()) {
primes[x]=0;
x = x+v;
}
}
}
return primes;
}
In the code fragment below, the numbers are filtered before they are inserted into the vector. The divisors come from the vector.
I'm also passing the vector by reference. This means that the huge vector won't be copied from the function to the caller. (Large chunks of memory take long times to copy)
vector<unsigned int> primes;
void calc_primes(vector<unsigned int>& primes, const unsigned int MAX)
{
// If MAX is less than 2, return an empty vector
// because 2 is the first prime and can't be placed in the vector.
if (MAX < 2)
{
return;
}
// 2 is the initial and unusual prime, so enter it without calculations.
primes.push_back(2);
for (unsigned int number = 3; number < MAX; number += 2)
{
bool is_prime = true;
for (unsigned int index = 0; index < primes.size(); ++index)
{
if ((number % primes[k]) == 0)
{
is_prime = false;
break;
}
}
if (is_prime)
{
primes.push_back(number);
}
}
}
This not the most efficient algorithm, but it follows the Sieve algorithm.
below is my version which basically uses a bit vector of bool and then goes through the odd numbers and a fast add to find multiples to set to false. In the end a vector is constructed and returned to the client of the prime values.
std::vector<int> getSieveOfEratosthenes ( int max )
{
std::vector<bool> primes(max, true);
int sz = primes.size();
for ( int i = 3; i < sz ; i+=2 )
if ( primes[i] )
for ( int j = i * i; j < sz; j+=i)
primes[j] = false;
std::vector<int> ret;
ret.reserve(primes.size());
ret.push_back(2);
for ( int i = 3; i < sz; i+=2 )
if ( primes[i] )
ret.push_back(i);
return ret;
}
Here is a concise, well explained implementation using bool type:
#include <iostream>
#include <cmath>
void find_primes(bool[], unsigned int);
void print_primes(bool [], unsigned int);
//=========================================================================
int main()
{
const unsigned int max = 100;
bool sieve[max];
find_primes(sieve, max);
print_primes(sieve, max);
}
//=========================================================================
/*
Function: find_primes()
Use: find_primes(bool_array, size_of_array);
It marks all the prime numbers till the
number: size_of_array, in the form of the
indexes of the array with value: true.
It implemenets the Sieve of Eratosthenes,
consisted of:
a loop through the first "sqrt(size_of_array)"
numbers starting from the first prime (2).
a loop through all the indexes < size_of_array,
marking the ones satisfying the relation i^2 + n * i
as false, i.e. composite numbers, where i - known prime
number starting from 2.
*/
void find_primes(bool sieve[], unsigned int size)
{
// by definition 0 and 1 are not prime numbers
sieve[0] = false;
sieve[1] = false;
// all numbers <= max are potential candidates for primes
for (unsigned int i = 2; i <= size; ++i)
{
sieve[i] = true;
}
// loop through the first prime numbers < sqrt(max) (suggested by the algorithm)
unsigned int first_prime = 2;
for (unsigned int i = first_prime; i <= std::sqrt(double(size)); ++i)
{
// find multiples of primes till < max
if (sieve[i] = true)
{
// mark as composite: i^2 + n * i
for (unsigned int j = i * i; j <= size; j += i)
{
sieve[j] = false;
}
}
}
}
/*
Function: print_primes()
Use: print_primes(bool_array, size_of_array);
It prints all the prime numbers,
i.e. the indexes with value: true.
*/
void print_primes(bool sieve[], unsigned int size)
{
// all the indexes of the array marked as true are primes
for (unsigned int i = 0; i <= size; ++i)
{
if (sieve[i] == true)
{
std::cout << i <<" ";
}
}
}
covering the array case. A std::vector implementation will include minor changes such as reducing the functions to one parameter, through which the vector is passed by reference and the loops will use the vector size() member function instead of the reduced parameter.
Here is a more efficient version for Sieve of Eratosthenes algorithm that I implemented.
#include <iostream>
#include <cmath>
#include <set>
using namespace std;
void sieve(int n){
set<int> primes;
primes.insert(2);
for(int i=3; i<=n ; i+=2){
primes.insert(i);
}
int p=*primes.begin();
cout<<p<<"\n";
primes.erase(p);
int maxRoot = sqrt(*(primes.rbegin()));
while(primes.size()>0){
if(p>maxRoot){
while(primes.size()>0){
p=*primes.begin();
cout<<p<<"\n";
primes.erase(p);
}
break;
}
int i=p*p;
int temp = (*(primes.rbegin()));
while(i<=temp){
primes.erase(i);
i+=p;
i+=p;
}
p=*primes.begin();
cout<<p<<"\n";
primes.erase(p);
}
}
int main(){
int n;
n = 1000000;
sieve(n);
return 0;
}
Here's my implementation not sure if 100% correct though :
http://pastebin.com/M2R2J72d
#include<iostream>
#include <stdlib.h>
using namespace std;
void listPrimes(int x);
int main() {
listPrimes(5000);
}
void listPrimes(int x) {
bool *not_prime = new bool[x];
unsigned j = 0, i = 0;
for (i = 0; i <= x; i++) {
if (i < 2) {
not_prime[i] = true;
} else if (i % 2 == 0 && i != 2) {
not_prime[i] = true;
}
}
while (j <= x) {
for (i = j; i <= x; i++) {
if (!not_prime[i]) {
j = i;
break;
}
}
for (i = (j * 2); i <= x; i += j) {
not_prime[i] = true;
}
j++;
}
for ( i = 0; i <= x; i++) {
if (!not_prime[i])
cout << i << ' ';
}
return;
}
I am following the same book now. I have come up with the following implementation of the algorithm.
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
inline void keep_window_open() { char ch; cin>>ch; }
int main ()
{
int max_no = 100;
vector <int> numbers (max_no - 1);
iota(numbers.begin(), numbers.end(), 2);
for (unsigned int ind = 0; ind < numbers.size(); ++ind)
{
for (unsigned int index = ind+1; index < numbers.size(); ++index)
{
if (numbers[index] % numbers[ind] == 0)
{
numbers.erase(numbers.begin() + index);
}
}
}
cout << "The primes are\n";
for (int primes: numbers)
{
cout << primes << '\n';
}
}
Here is my version:
#include "std_lib_facilities.h"
//helper function:check an int prime, x assumed positive.
bool check_prime(int x) {
bool check_result = true;
for (int i = 2; i < x; ++i){
if (x%i == 0){
check_result = false;
break;
}
}
return check_result;
}
//helper function:return the largest prime smaller than n(>=2).
int near_prime(int n) {
for (int i = n; i > 0; --i) {
if (check_prime(i)) { return i; break; }
}
}
vector<int> sieve_primes(int max_limit) {
vector<int> num;
vector<int> primes;
int stop = near_prime(max_limit);
for (int i = 2; i < max_limit+1; ++i) { num.push_back(i); }
int step = 2;
primes.push_back(2);
//stop when finding the last prime
while (step!=stop){
for (int i = step; i < max_limit+1; i+=step) {num[i-2] = 0; }
//the multiples set to 0, the first none zero element is a prime also step
for (int j = step; j < max_limit+1; ++j) {
if (num[j-2] != 0) { step = num[j-2]; break; }
}
primes.push_back(step);
}
return primes;
}
int main() {
int max_limit = 1000000;
vector<int> primes = sieve_primes(max_limit);
for (int i = 0; i < primes.size(); ++i) {
cout << primes[i] << ',';
}
}
Here is a classic method for doing this,
int main()
{
int max = 500;
vector<int> array(max); // vector of max numbers, initialized to default value 0
for (int i = 2; i < array.size(); ++ i) // loop for rang of numbers from 2 to max
{
// initialize j as a composite number; increment in consecutive composite numbers
for (int j = i * i; j < array.size(); j +=i)
array[j] = 1; // assign j to array[index] with value 1
}
for (int i = 2; i < array.size(); ++ i) // loop for rang of numbers from 2 to max
if (array[i] == 0) // array[index] with value 0 is a prime number
cout << i << '\n'; // get array[index] with value 0
return 0;
}
I think im late to this party but im reading the same book as you, this is the solution in came up with! Feel free to make suggestions (you or any!), for what im seeing here a couple of us extracted the operation to know if a number is multiple of another to a function.
#include "../../std_lib_facilities.h"
bool numIsMultipleOf(int n, int m) {
return n%m == 0;
}
int main() {
vector<int> rawCollection = {};
vector<int> numsToCheck = {2,3,5,7};
// Prepare raw collection
for (int i=2;i<=100;++i) {
rawCollection.push_back(i);
}
// Check multiples
for (int m: numsToCheck) {
vector<int> _temp = {};
for (int n: rawCollection) {
if (!numIsMultipleOf(n,m)||n==m) _temp.push_back(n);
}
rawCollection = _temp;
}
for (int p: rawCollection) {
cout<<"N("<<p<<")"<<" is prime.\n";
}
return 0;
}
Try this code it will be useful to you by using java question bank
import java.io.*;
class Sieve
{
public static void main(String[] args) throws IOException
{
int n = 0, primeCounter = 0;
double sqrt = 0;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println(“Enter the n value : ”);
n = Integer.parseInt(br.readLine());
sqrt = Math.sqrt(n);
boolean[] prime = new boolean[n];
System.out.println(“\n\nThe primes upto ” + n + ” are : ”);
for (int i = 2; i<n; i++)
{
prime[i] = true;
}
for (int i = 2; i <= sqrt; i++)
{
for (int j = i * 2; j<n; j += i)
{
prime[j] = false;
}
}
for (int i = 0; i<prime.length; i++)
{
if (prime[i])
{
primeCounter++;
System.out.print(i + ” “);
}
}
prime = new boolean[0];
}
}