python linspace in c++ - python

im trying to write a similar version of python's numpy.linspace function.
double linspace(int a, int b, int c){
double line[c];
double delta =b-a/(c-1);
for (int i=0; i<c; ++i){
line[i]=0 + (i*delta);
}
return line;
with a and b being the first and the last component in the array, and c specifying the number of elements in the array. But when i compile this script it returns:
linspace.cpp: In function ‘double linspace(int, int, int)’:
linspace.cpp:11:9: error: cannot convert ‘double*’ to ‘double’ in return
return line;
^
would anyone happen to knw how to solve this problem?

How about something like this:
#include <iostream>
#include <vector>
template<typename T>
std::vector<double> linspace(T start_in, T end_in, int num_in)
{
std::vector<double> linspaced;
double start = static_cast<double>(start_in);
double end = static_cast<double>(end_in);
double num = static_cast<double>(num_in);
if (num == 0) { return linspaced; }
if (num == 1)
{
linspaced.push_back(start);
return linspaced;
}
double delta = (end - start) / (num - 1);
for(int i=0; i < num-1; ++i)
{
linspaced.push_back(start + delta * i);
}
linspaced.push_back(end); // I want to ensure that start and end
// are exactly the same as the input
return linspaced;
}
void print_vector(std::vector<double> vec)
{
std::cout << "size: " << vec.size() << std::endl;
for (double d : vec)
std::cout << d << " ";
std::cout << std::endl;
}
int main()
{
std::vector<double> vec_1 = linspace(1, 10, 3);
print_vector(vec_1);
std::vector<double> vec_2 = linspace(6.0, 23.4, 5);
print_vector(vec_2);
std::vector<double> vec_3 = linspace(0.0, 2.0, 1);
print_vector(vec_3);
std::vector<double> vec_4 = linspace(0.0, 2.0, 0);
print_vector(vec_4);
return 0;
}
C++ result:
size: 3
1 5.5 10
size: 5
6 10.35 14.7 19.05 23.4
size: 1
0
size: 0
Numpy result:
In [14]: np.linspace(1, 10, 3)
Out[14]: array([ 1. , 5.5, 10. ])
In [15]: np.linspace(6, 23.4, 5)
Out[15]: array([ 6. , 10.35, 14.7 , 19.05, 23.4 ])
In [16]: np.linspace(0.0, 2.0, 1)
Out[16]: array([ 0.])
In [17]: np.linspace(0.0, 2.0, 0)
Out[17]: array([], dtype=float64)

What you are trying to do what won't work. First off you are allocating the memory on the stack WITHIN linspace with
double line[c];
You either new to allocate the memory before the call and pass it in, or allocate it dynamically and return it (and remember to free it later).
To allocate dynamically you can do the following:
double * line = new double[c];
Again, this will need to be freed like so at some point later when you are finished with it, otherwise you will have a memory leak.
delete line[];
Also double line[c]; creates an array of doubles and line points to that. So line is a double *. You specified the return type of the function as double

Related

Unusual behaviour of Ant Colony Optimization for Closest String Problem in Python and C++

This is probably going to be a long question, I apologize in advance.
I'm working on a project with the goal of researching different solutions for the closest string problem.
Let s_1, ... s_n be strings of length m. Find a string s of length m such that it minimizes max{d(s, s_i) | i = 1, ..., n}, where d is the hamming distance.
One solution that has been tried is one using ant colony optimization, as decribed here.
The paper itself does not go into implementation details, so I've done my best on efficiency. However, efficiency is not the only unusual behaviour.
I'm not sure whether it's common pratice to do so, but I will present my code through pastebin since I believe it would overwhelm the thread if I should put it directly here. If that turns out to be a problem, I won't mind editing the thread to put it here directly. As all the previous algorithms I've experimented with, I've written this one in python initially. Here's the code:
def solve_(self, problem: CSProblem) -> CSSolution:
m, n, alphabet, strings = problem.m, problem.n, problem.alphabet, problem.strings
A = len(alphabet)
rho = self.config['RHO']
colony_size = self.config['COLONY_SIZE']
global_best_ant = None
global_best_metric = m
ants = np.full((colony_size, m), '')
world_trails = np.full((m, A), 1 / A)
for iteration in range(self.config['MAX_ITERS']):
local_best_ant = None
local_best_metric = m
for ant_idx in range(colony_size):
for next_character_index in range(m):
ants[ant_idx][next_character_index] = random.choices(alphabet, weights=world_trails[next_character_index], k=1)[0]
ant_metric = utils.problem_metric(ants[ant_idx], strings)
if ant_metric < local_best_metric:
local_best_metric = ant_metric
local_best_ant = ants[ant_idx]
# First we perform pheromone evaporation
for i in range(m):
for j in range(A):
world_trails[i][j] = world_trails[i][j] * (1 - rho)
# Now, using the elitist strategy, only the best ant is allowed to update his pheromone trails
best_ant_ys = (alphabet.index(a) for a in local_best_ant)
best_ant_xs = range(m)
for x, y in zip(best_ant_xs, best_ant_ys):
world_trails[x][y] = world_trails[x][y] + (1 - local_best_metric / m)
if local_best_metric < global_best_metric:
global_best_metric = local_best_metric
global_best_ant = local_best_ant
return CSSolution(''.join(global_best_ant), global_best_metric)
The utils.problem_metric function looks like this:
def hamming_distance(s1, s2):
return sum(c1 != c2 for c1, c2 in zip(s1, s2))
def problem_metric(string, references):
return max(hamming_distance(string, r) for r in references)
I've seen that there are a lot more tweaks and other parameters you can add to ACO, but I've kept it simple for now. The configuration I'm using is is 250 iterations, colony size od 10 ants and rho=0.1. The problem that I'm testing it on is from here: http://tcs.informatik.uos.de/research/csp_cssp , the one called 2-10-250-1-0.csp (the first one). The alphabet consists only of '0' and '1', the strings are of length 250, and there are 10 strings in total.
For the ACO configuration that I've mentioned, this problem, using the python solver, gets solved on average in 5 seconds, and the average target function value is 108.55 (simulated 20 times). The correct target function value is 96. Ironically, the 5-second average is good compared to what it used to be in my first attempt of implementing this solution. However, it's still surprisingly slow.
After doing all kinds of optimizations, I've decided to try and implement the exact same solution in C++ so see whether there will be a significant difference between the running times. Here's the C++ solution:
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <random>
#include <chrono>
#include <map>
class CSPProblem{
public:
int m;
int n;
std::vector<char> alphabet;
std::vector<std::string> strings;
CSPProblem(int m, int n, std::vector<char> alphabet, std::vector<std::string> strings)
: m(m), n(n), alphabet(alphabet), strings(strings)
{
}
static CSPProblem from_csp(std::string filepath){
std::ifstream file(filepath);
std::string line;
std::vector<std::string> input_lines;
while (std::getline(file, line)){
input_lines.push_back(line);
}
int alphabet_size = std::stoi(input_lines[0]);
int n = std::stoi(input_lines[1]);
int m = std::stoi(input_lines[2]);
std::vector<char> alphabet;
for (int i = 3; i < 3 + alphabet_size; i++){
alphabet.push_back(input_lines[i][0]);
}
std::vector<std::string> strings;
for (int i = 3 + alphabet_size; i < input_lines.size(); i++){
strings.push_back(input_lines[i]);
}
return CSPProblem(m, n, alphabet, strings);
}
int hamm(const std::string& s1, const std::string& s2) const{
int h = 0;
for (int i = 0; i < s1.size(); i++){
if (s1[i] != s2[i])
h++;
}
return h;
}
int measure(const std::string& sol) const{
int mm = 0;
for (const auto& s: strings){
int h = hamm(sol, s);
if (h > mm){
mm = h;
}
}
return mm;
}
friend std::ostream& operator<<(std::ostream& out, CSPProblem problem){
out << "m: " << problem.m << std::endl;
out << "n: " << problem.n << std::endl;
out << "alphabet_size: " << problem.alphabet.size() << std::endl;
out << "alphabet: ";
for (const auto& a: problem.alphabet){
out << a << " ";
}
out << std::endl;
out << "strings:" << std::endl;
for (const auto& s: problem.strings){
out << "\t" << s << std::endl;
}
return out;
}
};
std::random_device rd;
std::mt19937 gen(rd());
int get_from_distrib(const std::vector<float>& weights){
std::discrete_distribution<> d(std::begin(weights), std::end(weights));
return d(gen);
}
int max_iter = 250;
float rho = 0.1f;
int colony_size = 10;
int ant_colony_solver(const CSPProblem& problem){
srand(time(NULL));
int m = problem.m;
int n = problem.n;
auto alphabet = problem.alphabet;
auto strings = problem.strings;
int A = alphabet.size();
float init_pher = 1.0 / A;
std::string global_best_ant;
int global_best_matric = m;
std::vector<std::vector<float>> world_trails(m, std::vector<float>(A, 0.0f));
for (int i = 0; i < m; i++){
for (int j = 0; j < A; j++){
world_trails[i][j] = init_pher;
}
}
std::vector<std::string> ants(colony_size, std::string(m, ' '));
for (int iteration = 0; iteration < max_iter; iteration++){
std::string local_best_ant;
int local_best_metric = m;
for (int ant_idx = 0; ant_idx < colony_size; ant_idx++){
for (int next_character_idx = 0; next_character_idx < m; next_character_idx++){
char next_char = alphabet[get_from_distrib(world_trails[next_character_idx])];
ants[ant_idx][next_character_idx] = next_char;
}
int ant_metric = problem.measure(ants[ant_idx]);
if (ant_metric < local_best_metric){
local_best_metric = ant_metric;
local_best_ant = ants[ant_idx];
}
}
// Evaporation
for (int i = 0; i < m; i++){
for (int j = 0; j < A; j++){
world_trails[i][j] = world_trails[i][j] + (1.0 - rho);
}
}
std::vector<int> best_ant_xs;
for (int i = 0; i < m; i++){
best_ant_xs.push_back(i);
}
std::vector<int> best_ant_ys;
for (const auto& c: local_best_ant){
auto loc = std::find(std::begin(alphabet), std::end(alphabet), c);
int idx = loc- std::begin(alphabet);
best_ant_ys.push_back(idx);
}
for (int i = 0; i < m; i++){
int x = best_ant_xs[i];
int y = best_ant_ys[i];
world_trails[x][y] = world_trails[x][y] + (1.0 - static_cast<float>(local_best_metric) / m);
}
if (local_best_metric < global_best_matric){
global_best_matric = local_best_metric;
global_best_ant = local_best_ant;
}
}
return global_best_matric;
}
int main(){
auto problem = CSPProblem::from_csp("in.csp");
int TRIES = 20;
std::vector<int> times;
std::vector<int> measures;
for (int i = 0; i < TRIES; i++){
auto start = std::chrono::high_resolution_clock::now();
int m = ant_colony_solver(problem);
auto stop = std::chrono::high_resolution_clock::now();
int duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start).count();
times.push_back(duration);
measures.push_back(m);
}
float average_time = static_cast<float>(std::accumulate(std::begin(times), std::end(times), 0)) / TRIES;
float average_measure = static_cast<float>(std::accumulate(std::begin(measures), std::end(measures), 0)) / TRIES;
std::cout << "Average running time: " << average_time << std::endl;
std::cout << "Average solution: " << average_measure << std::endl;
std::cout << "all solutions: ";
for (const auto& m: measures) std::cout << m << " ";
std::cout << std::endl;
return 0;
}
The average running time now is only 530.4 miliseconds. However, the average target function value is 122.75, which is significantly higher than that of the python solution.
If the average function values were the same, and the times were as they are, I would simply write this off as 'C++ is faster than python' (even though the difference in speed is also very suspiscious). But, since C++ yields worse solutions, it leads me to believe that I've done something wrong in C++. What I'm suspiscious of is the way I'm generating an alphabet index using weights. In python I've done it using random.choices as follows:
ants[ant_idx][next_character_index] = random.choices(alphabet, weights=world_trails[next_character_index], k=1)[0]
As for C++, I haven't done it in a while so I'm a bit rusty on reading cppreference (which is a skill of its own), and the std::discrete_distribution solution is something I've plain copied from the reference:
std::random_device rd;
std::mt19937 gen(rd());
int get_from_distrib(const std::vector<float>& weights){
std::discrete_distribution<> d(std::begin(weights), std::end(weights));
return d(gen);
}
The suspiscious thing here is the fact that I'm declaring the std::random_device and std::mt19937 objects globally and using the same ones every time. I have not been able to find an answer to whether this is the way they're meant to be used. However, if I put them in the function:
int get_from_distrib(const std::vector<float>& weights){
std::random_device rd;
std::mt19937 gen(rd());
std::discrete_distribution<> d(std::begin(weights), std::end(weights));
return d(gen);
}
the average running time gets significantly worse, clocking in at 8.84 seconds. However, even more surprisingly, the average function value gets worse as well, at 130.
Again, if only one of the two things changed (say if only the time went up) I would have been able to draw some conclusions. This way it only gets more confusing.
So, does anybody have an idea of why this is happening?
Thanks in advance.
MAJOR EDIT: I feel embarrased having asked such a huge question when in fact the problem lies in a simple typo. Namely in the evaporation step in the C++ version I put a + instead of a *.
Now the algorithms behave identically in terms of average solution quality.
However, I could still use some tips on how to optimize the python version.
Apart form the dumb mistake I've mentioned in the question edit, it seems I've finally found a way to optimize the python solution decently. First of all, keeping world_trails and ants as numpy arrays instead of lists of lists actually slowed things down. Furthermore, I actually stopped keeping a list of ants altogether since I only ever need the best one per iteration.
Lastly, running cProfile indicated that a lot of the time was spent on random.choices, therefore I've decided to implement my own version of it suited specifically for this case. I've done this by pre-computing total weight sum per character for each next iteration (in the trail_row_wise_sums array), and using the following function:
def fast_pick(arr, weights, ws):
r = random.random()*ws
for i in range(len(arr)):
if r < weights[i]:
return arr[i]
r -= weights[i]
return 0
The new version now looks like this:
def solve_(self, problem: CSProblem) -> CSSolution:
m, n, alphabet, strings = problem.m, problem.n, problem.alphabet, problem.strings
A = len(alphabet)
rho = self.config['RHO']
colony_size = self.config['COLONY_SIZE']
miters = self.config['MAX_ITERS']
global_best_ant = None
global_best_metric = m
init_pher = 1.0 / A
world_trails = [[init_pher for _ in range(A)] for _ in range(m)]
trail_row_wise_sums = [1.0 for _ in range(m)]
for iteration in tqdm(range(miters)):
local_best_ant = None
local_best_metric = m
for _ in range(colony_size):
ant = ''.join(fast_pick(alphabet, world_trails[next_character_index], trail_row_wise_sums[next_character_index]) for next_character_index in range(m))
ant_metric = utils.problem_metric(ant, strings)
if ant_metric <= local_best_metric:
local_best_metric = ant_metric
local_best_ant = ant
# First we perform pheromone evaporation
for i in range(m):
for j in range(A):
world_trails[i][j] = world_trails[i][j] * (1 - rho)
# Now, using the elitist strategy, only the best ant is allowed to update his pheromone trails
best_ant_ys = (alphabet.index(a) for a in local_best_ant)
best_ant_xs = range(m)
for x, y in zip(best_ant_xs, best_ant_ys):
world_trails[x][y] = world_trails[x][y] + (1 - 1.0*local_best_metric / m)
if local_best_metric < global_best_metric:
global_best_metric = local_best_metric
global_best_ant = local_best_ant
trail_row_wise_sums = [sum(world_trails[i]) for i in range(m)]
return CSSolution(global_best_ant, global_best_metric)
The average running time is now down to 800 miliseconds (compared to 5 seconds that it was before). Granted, applying the same fast_pick optimization to the C++ solution did also speed up the C++ version (around 150 ms) but I guess now I can write it off as C++ being faster than python.
Profiler also showed that a lot of the time was spent on calculating Hamming distances, but that's to be expected, and apart from that I see no other way of computing the Hamming distance between arbitrary strings more efficiently.

Incrementing a for loop upward in C

I am hoping to mimic a Python for loop with the range() function in C. I'd like to accomplish a task an increasing number of times each loop until I reach the value of a given variable, in this case 5 (for the variable h). Here it is in Python:
x = 5
y = 0
while x > y:
for i in range(y+1):
print("#",end='')
print('')
y+=1
Output:
#
##
###
####
#####
I was able to accomplish the opposite (executing something a decreasing number of times) in C, as below:
{
int h = 5;
while (h > 0)
{
for (int i = 0; i < h; i++)
{
printf("#");
}
printf("\n");
h--;
}
}
Output:
#####
####
###
##
#
When I've attempted the top version in C, with the increasing number of executions, I run into the problem of not knowing how to control the various incrementing and decrementing variables.
I suggest you should think simply:
Increment up the number of # to print
Use loop to print that number of #
#include <stdio.h>
int main(void)
{
int h = 5;
for (int c = 1; c <= h; c++) // the number of # to print
{
for (int i = 0; i < c; i++)
{
printf("#");
}
printf("\n");
}
return 0;
}
Another way is simply writing in just the same way as the Python version:
#include <stdio.h>
int main(void)
{
int x = 5;
int y = 0;
while (x > y)
{
for (int i = 0; i < y+1; i++)
{
printf("#");
}
printf("\n");
y += 1;
}
return 0;
}
The solution in C:
#include <stdio.h>
int main ()
{
int x = 5;
int y = 0;
while (x > y)
{
for (int i=0;i<y+1;i++)
{
printf("#");
}
printf("\n");
}
return 0;
}
In Python, in the for loop, the variable is initialized as zero and increments by 1 by default. But in C, you need to do it explicitly.

Matrix multiplication speed BLAS/Eigen and Numpy

I am benchmarking matrix multiplication for different libraries as I am thinking of rewriting some cython code to native c++. However the simple tests seem to imply that numpy is faster than BLAS or eigen for simple matrix multiplications.
I have written the following files:
#!test_blas.cpp
#include <random>
#include <cstdio>
#include <stdlib.h>
#include <iostream>
#include <cblas.h>
int main ( int argc, char* argv[] ) {
// Random numbers
std::mt19937_64 rnd;
std::uniform_real_distribution<double> doubleDist(0, 1);
// Create arrays that represent the matrices A,B,C
const int n = 2000;
double* A = new double[n*n];
double* B = new double[n*n];
double* C = new double[n*n];
// Fill A and B with random numbers
for(uint i =0; i <n; i++){
for(uint j=0; j<n; j++){
A[i*n+j] = doubleDist(rnd);
B[i*n+j] = doubleDist(rnd);
}
}
// Calculate A*B=C
clock_t start = clock();
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1.0, A, n, B, n, 0.0, C, n);
clock_t end = clock();
double time = double(end - start)/ CLOCKS_PER_SEC;
std::cout<< "Time taken : " << time << std::endl;
// Clean up
delete[] A;
delete[] B;
delete[] C;
return 0;
}
#!test_eigen.cpp
#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
int n_a_rows = 2000;
int n_a_cols = 2000;
int n_b_rows = n_a_cols;
int n_b_cols = 2000;
MatrixXd a(n_a_rows, n_a_cols);
for (int i = 0; i < n_a_rows; ++ i)
for (int j = 0; j < n_a_cols; ++ j)
a (i, j) = n_a_cols * i + j;
MatrixXd b (n_b_rows, n_b_cols);
for (int i = 0; i < n_b_rows; ++ i)
for (int j = 0; j < n_b_cols; ++ j)
b (i, j) = n_b_cols * i + j;
MatrixXd d (n_a_rows, n_b_cols);
clock_t begin = clock();
d = a * b;
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
std::cout << "Time taken : " << elapsed_secs << std::endl;
}
#!test_numpy.py
import numpy as np
import time
N = 2000
a = np.random.rand(N, N)
b = np.random.rand(N, N)
start = time.time()
c = a.dot(b)
print(f"Time taken : {time.time() - start}")
Finally I created the following test file
#!test_matrix.sh
c++ -O2 -march=native -std=c++11 -I /usr/include/eigen3 test_eigen.cpp -o eigen
c++ -O2 -march=native -std=c++11 test_blas.cpp -o blas -lcblas
echo "testing BLAS"
./blas
echo "testing Eigen"
./eigen
echo "testing numpy"
python test_numpy.py
which yields the output
testing BLAS
Time taken : 1.63807
testing Eigen
Time taken : 0.795115
testing numpy
Time taken : 0.28397703170776367
Now my question is, how come numpy is the fastest of these tests? Am I missing something with regards to optimizations?
One thing could be that numpy uses threading to compute the matrix product. Adding the compiler flag -fopenmp however yields worse performance for eigen and BLAS.
I am using g++ version 9.0.3-1. Numpy is version 1.18.1 using python 3.8.2. Thanks in advance.

Can't correctly convert Numpy array to c array for Python Extension (c++)

I'm developing a Python extension in c++. I'm am really rusty in c++ however and don't have the necessary experience to figure this out it seems. I'm trying to read in numpy arrays, do the calculations I want to do and then return a numpy array. The problem I'm having is converting the numpy array to something of a normal Double array in 'c format'. I tried two methods to convert the data but both result in the same, seems to be storing the memory locations when I print out the arrays, not the actual values
Here is the code with some comments.
static PyObject* mymodule_function(PyObject *self, PyObject *args){
PyArrayObject *x_obj,*y_obj;
double *x, *y;
if (!PyArg_ParseTuple(args, "O!O!", &PyArray_Type, &x_obj,&PyArray_Type, &y_obj)) return NULL;
if (NULL == x_obj) return NULL;
if (NULL == y_obj) return NULL;
npy_intp N = PyArray_DIM(x_obj, 0);
std::cout << int(N) << std::endl; //Correctly prints out size of array
//method 1 I tried to convert data
x = (double*)x_obj->data;
//method 2 that I tried
y = (double*)PyArray_DATA(y_obj);
// Debug printing.
for (int i = 0; i < (int)N; i ++){
std::cout << x[i] << std::endl;
std::cout << y[i] << std::endl;
}
//prints out array correctly
double z[N];
myfunction(x,y,z,(int)N);
// Debug printing.
for (int i = 0; i < (int)N; i ++){
std::cout << z[i] << std::endl;
}
//prints out array correctly
npy_intp dims[1];
dims[0] = N;
PyObject *pyArray = PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, z);
PyObject *ret = Py_BuildValue("O", pyArray);
return ret;
}
and the Python code I use:
import numpy as np
import mymodule as mm
a = np.array([1,2,3],dtype=np.float64)
b = np.array([4,5,6],dtype=np.float64)
c = np.zeros(shape=(1,3),dtype=np.float64)
c = mm.function(a,b)
print(c)
Specifying the data type in your python deceleration for a,b,c as dtype=np.float64. Double in C parlance is 64 bit float. using np.array like the way you've used it usually returns np.int64. using np.array like so will return a np.float64
a=np.array([1.,2.,3.])

Fibonacci Sequence and issues with return?

I am trying to learn c++ having already started programming in python. This is a simple program to calculate the fibonacci numbers between two values a,b. However when i run the code only the number 1 is printed and I can not figure out why. I think it is something to do with using return inside the for loop. Any help would be greatly appreciated
#include <iostream>
using namespace std;
int fibo(int b,int a=0){
int x=0;
int y=1;
for(int i=0; i<=b; i++){
int x0=x;
int z=x+y;
x=y;
y=z;
if(x>a){
return x0;
}
}
}
int main()
{
cout << fibo(100)<<endl;
return 0;
}
Here is the python function just for reference
def fibo(b,a=0):
x=0
y=1
while x<=b:
z=x+y
x0=x
x=y
y=z
if x>a:
print x0
I have also tried the following in c++
#include <iostream>
using namespace std;
int fibo(int b,int a=0){
int x=0;
int y=1;
for(int i=0; i<=b; i++){
int x0=x;
int z=x+y;
x=y;
y=z;
if(x>a){
cout << x0 <<endl;
}
}
}
int main()
{
fibo(100);
return 0;
}
However this gives fibonacci numbers beyond the value of b
Here's the exact port of your code from Python to C++
#include <iostream>
using namespace std;
void fibo(int b,int a=0){
int x=0;
int y=1;
int z, x0;
while( x <= b ) {
z= x + y;
x0 = x;
x = y;
y = z;
if(x > a) {
cout << x0 << endl;
}
}
}
int main()
{
fibo(100);
return 0;
}
In your Python code, if there's no explicit return, the default return value of the function will be None. In C++, that's equivalent to a void function.
Why didn't your for loop work?
The for loop is designed to iterate a number of times. Its syntax is:
for (initialization; condition; increase) statement;
Like the while-loop, this loop repeats statement while condition is true. But, in addition, the for loop provides specific OPTIONAL locations to contain an initialization and an increase expression, executed before the loop begins the first time, and after each iteration, respectively.
initialization is executed. Generally, this declares a counter
variable, and sets it to some initial value. This is executed a
single time, at the beginning of the loop.
condition is checked. If it is true, the loop continues; otherwise,
the loop ends, and statement is skipped, going directly to step 5.
statement is executed. As usual, it can be either a single statement
or a block enclosed in curly braces { }.
increase is executed, and the loop gets back to step 2.
the loop ends: execution continues by the next statement after it.
Read more here: http://www.cplusplus.com/doc/tutorial/control/#for.
So let's break down your loop:
int x=0; // initialize x to 0
int y=1; // initialize y to 1
for(
int i=0; // initialize i to 0
i<=b; // keep looping until i is less than or equal to b (a variable passed in)
i++ // after every single loop iteration, increment i by 1
) {
int x0=x; // initialize x0 to x
int z=x+y; // initialize z to (x + y)
x=y; // assign the value of y to x
y=z; // assign the value of z to y
if(x>a){ // if x is greater than a, print the value of x0
cout << x0 <<endl;
}
}
In your Python code, you don't have an i, you use x as your loop invariant. So that should be the condition of your for loop: x <= b. The initialization part should be the variables you set before you loop, so: int x = 0, y = 1, x0, z should be the initialization. The last part is the increment. In your python code, your increment is x = y, but in a for loop, that part is executed after the iteration is done, so we can't just set x = y in the increment part of the for loop since y = z is executed before the increment part. What we can do is use a bit of algebra: z = y + x, so we can get the value of y by subtracting x from z: z - x.
This makes the for loop:
void fibo2(int b,int a=0){
for(
int x = 0, y = 1, x0, z;
x <= b;
x = (z-x)
) {
x0 = x;
z = x+y;
y = z;
if(x > a){
cout << x0 <<endl;
}
}
}
Hope this helps.
Try this:
#include <iostream>
using namespace std;
int fibo(int b,int a=0){
int x=0;
int y=1;
while(x<=b)
{
int z=x+y;
int x0=x;
x=y;
y=z;
if(x>a && x<b)
{
cout << x << " ";
}
}
}
int main()
{
fibo(100);
return 0;
}
http://ideone.com/225KIY
The usual mathematical (recursive) method to compute the sequence up to some limit (this is not necessarily the best/most efficient method!): Link to demo here
#include <iostream>
using namespace std;
int fibo(int x)
{
if (x == 0) return 0;
if (x == 1) return 1;
return fibo(x-1)+fibo(x-2);
}
int main()
{
int j=1,limit=100;
do
{
cout<< fibo(j) <<'\t';
++j;
} while(fibo(j)<=limit);
return 0;
}

Categories