For looping an array? - c

Just starting to grasp the ropes on c-programming, but I'm trying to create a function that can compute numbers from a given base to a decimal format.
(base_to_int)
For example,
digits1[] = {2, 3, 4, 5} in base 10 = 5432
and
digits2[] = {5, 6, 7} in base 8 = 501
it looks like when I try to run a for loop through, it doesn't seem to be computing it, and I keep getting the last digit in the array (for digits1, the answer for the output I keep getting is "5")...
why can't I run a for loop through the array?
CODE:
ndigits = number of digits in the array, digits = array, base = the base the array number is in.
int base_to_int(int ndigits, int* digits, int base)
{
for (int n = 0 ; n <= ndigits - 1 ; n++)
{
int a = digits[n];
return a * pow(base,n);
}
}
for this code, I keep getting the output "2" when I try to compile it.

You're returning the first result of the calculations, remember, return ends the execution of the function and simply returns the value, so you're having only one iteration and not looping and summing all values, your code is equivalent to:
return digits[0] * pow(base,0);
Change
return a * pow(base, n);
to
sum += a * pow(base, n)
You should return sum outside the loop, when you finish the calculations (don't forget to initialize sum to 0 outside the loop).

As Maroun Maroun said,when you write the return statement,the function returns and never computes the later part.

Related

Iterate a long integer and then append number to an array in C

So I'm prompting the user for a number, stored as a long int, then I want to do a for loop and iterate that long int, getting all the odd position numbers in a odd array and all the even position numbers in a even array. I'm trying to resolve the credit problem set from CS50
#include <stdio.h>
#include <cs50.h>
int main(void)
{
long even[] = {}, odd[] = {};
long cc = get_long("Number: ");
}
Basically I'm trying to get this:
If long cc = 12345678912345, then even should be even[7] = {1, 3, 5, 7, 9, 2, 4} and odd should be odd[7] = {2, 4, 6, 8, 1, 3, 5}
I don't really know how I would be able to iterate over long cc to then add the specific number I need into the array
The main problem you have is that arrays in C have a fixed size, set when they are created, and that size cannot be changed. So there's no way to "append" to an array.
The usual way to deal with that is to create an array with a maximum size (or capacity) and track the "in use" part of the array with a separate variable (often called 'size'). At any given time, the array elements from 0 to size-1 are "in use" and valid, while those from size to capacity-1 are "free" and might contain garbage values that will be ignored.
Since the array and the size variable are so intimately connected, it is common to combine them into a struct to make things easier to manage:
#define MAX_ARRAY_SIZE 100
struct long_array {
size_t size;
long data[MAX_ARRAY_SIZE];
};
Now you can initialize an empty array with struct long_array odd = { 0 }; and you could then append to this array with
if (odd.size == MAX_ARRAY_SIZE) {
/* always check for errors or unexpected situations! */
fprintf(stderr, "array overflow\n");
exit(1); }
odd.data[odd.size++] = new_value;
of course, this will end up allocating the maximum amount for every array, so the limit needs to be fairly small. You can make this more flexible by allocating the array on the heap and storing the capacity in the array as well as the size:
struct long_array {
size_t size, capacity;
long *data;
};
but this requires more management to track when the array needs to be resized or freed.
that's fairly easy, just allocate two array with how many numbers are in cc using something like
int temp = cc, i = 0;
while (temp > 0) {i++; cc /= 10;}
Then calculate ur stuff like this:
while (cc > 0)
{
newNumber = cc/10;
newDigit = CC % 10
if (newNumber % 2 == 0) /*newDigit is even*/
else /*newDigit is odd*/
cc = newNumber;
}
You can use the modulo operator % to get each digit. The modulo operator basically gives you the remainder so if you do % 10 then it will give you the last digit. So 123 % 10 = 3. Then you divide the credit card number by 10 and repeat the process to get the next digit. Ex 123/10 = 12, then 12 % 10 is 2. If you make a counter variable to count how many times you've done the loop, that will give you the position. If you do position % 2, that will tell you if it is odd or even.
while (CC > 0)
digit = CC % 10
if (position % 2 == 1) //it's odd
else //its even
CC = CC/10 //to prepare for next iteration of the loop
position = position + 1 //position starts at right side of CC number
One of the other proposed answers here determines if the digit's value is odd or even, but you're trying to determine if the digit is in an even or odd position. The other proposed answer uses an array, which is something you learn about later in the course and isn't what the class is trying to teach you now.
The solution I've suggested is in line with what has been covered by your class so far. Later you will learn about arrays and you can approach this problem differently. Later in the course, you need to do this same problem in Python and that time I took in the value as a string because you can treat the full credit card number as an array and then each digit is just an element in that array. creditcardnumberarray[0] would be the first digit for example. You would need to change each digit from a Char to a Int before doing your checksum. You can do this conversion by subtracting the digit char from the char '0'. So int digitAsInt = digitAsChar - '0'

Finding the missing values from a given range

How can I calculate all the missing values between a particular range of numbers
where a missing number is equal to average of next and previous values of given input range
Example
Number of missing values = 2
Array : [5, ?, ?, 20]
Result: 5,10,15,20
Simply doing (5+25)/4+1 i.e. missing values+1 gives you 5 which we add to our first value gives 5 10 15 20 but doesn't work with other examples like
[6,?,?,?,20] (3 missing values)
Maybe you can try something like calculate the difference between the first and the last number you know, 20-5=15 on the example, and now you just divivide it to the number of "steps" you want to get the last one (number of missing number + 1), 15/3 = 5 on the example, and now you just add that quantity to each element to get the next one.
Something like this:
[5, (5+5), ((5+5)+5), 20]
You can verify it works for the second example too with 3 missing values.
Your condition that each number is equal to the average of the next and previous numbers, which you could write as:
xi = (xi+1 + xi-1) / 2
can easily be rearranged to:
xi - xi-1 = xi+1 - xi
In other words, the differences between adjacent numbers are all the same.
So this is just a simple linear interpolation. As you've tagged this with C, here's a simple C function to evaluate your example:
#include <stdio.h>
void calc_values(float start, float end, int n) {
int i;
for(i = 1; i <= n; i++)
printf("%f\n",
start + (end - start) * i / (n + 1));
}
int main()
{
calc_values(6, 20, 3);
return 0;
}
which gives:
9.500000
13.000000
16.500000

How do I deal with specific elements only in an array?

So I know how to add up all the elements of an array using a for loop. But how would I go about adding up only the positive elements?
Say my array included {3, -9, 2, -10}
I want to: 3 + 2 (giving 5)
NOT: 3 +-9 +2 +-10 (giving -14)
Also how would I get the amount of positive elements in an array? (i.e. in this example there are two positive elements)
Im using Java/Eclipse
Thanks so much for the answers - i now know what to do! This is my first time here - do i have to mark this as answered or something?
You can just add a condition in your loop :
arrays = {3, -9, 2, -10};
sum = 0;
nb_elem = 0;
for (i = 0 ; i < arrays.length ; i++)
{
if (arrays[i] > 0)
{
sum += arrays[i];
nb_elem++;
}
}
I don't know what language you are using, so I'll give you example in Python
def sum_up_positive_values(array):
result = 0
for value in array:
if value > 0:
result += value
return result

undefined behaviour of srand and rand

I am trying to generate random number using srand and rand. Here I want to generate specific number of digit. When I am executing my program at some time if I ask to generate 5 digit number number it is not giving me desired output.
My code is
for(k=0;k<n;k++)
{
temp = temp*10;
}
srand(time(NULL));
i = rand()%temp;
printf("%d\n",i);
k = 0;
temp = n;
while(i != 0)
{
arr1[n+k] = i%10;
i = i/10;
n--;
}
Output
Number of digits you want : 5
2031
while loop 1
while loop 3
while loop 0
while loop 2
N is 1
arr1[1] = 10651312
arr1[2] = 2
arr1[3] = 0
arr1[4] = 3
arr1[5] = 1
tell me where is the problem for getting desired number of digits.
Edit
I run that code around 100 times and out of those four time it is not working, rest is fine...
The problem is you're looping on the size of the random number you've generated and not the size of the array. In your example you want five digits but your code has generated a four digit number, 2031. This means that in the iteration of your bottom loop
... n = 2, i = 2: store a[2] = 2, i = 0
... n = 1, i = 0: loop condition failed, a[1] never set
which leaves random garbage in a[1]. If your random number did in fact contain 5 digits, not 4, then it would have completed the loop correctly.
Instead you want to loop over n
for(int j = n; j > 0; --j)
{
arr1[n+j] = i%10;
i = i/10;
}
Note that this is still using the array as 1-based, whereas in c arrays are 0-based, i.e. they start at element 0, i.e. in order to use arr1[5] you need to have malloced or declared 6 array elements or 6*sizeof(int) bytes. Also note that you should use better variable names than temp, and there's no benefit to reusing the variable: your compiler will automatically reuse registers and sort that out for you.
There are several problems here.
First, call srand() once before actually producing random numbers.
Second, your method taking the returned number modulo some power of 10 will, of course, also return numbers that are lower. For example, n%100000 could be anything from 0 to 99999.
n = rand() % (largest - smallest + 1) + smallest;
If you want a 5 digit number, what is the smallest 5 digit number? Do the same for the largest number. That can be used for any number range with no need to fill an array or anything.
Now you just need to figure out how to generate the largest and smallest values for the number of digits specified.
Happy coding!

Weighted random number generation

I would like to generate weighted random numbers in an exact manner. I can explain exact with an example: My input array is [1, 2, 3] and their weights are again [1, 2, 3]. In that case I expect to see 1 for 1 times, 2 for 2 times and 3 for 3. Like 3 -> 2 -> 3 -> 1 -> 3 -> 2...
I am implementing random number generation with rand() to get a range between [0, sum_of_weights). sum_of_weights = 1 + 2 + 3 = 6 for the example above. I searched for existing solutions on the Internet, however the result is not what I want. Sometimes I got 2 more than 2 times and no 1 in the sequence. Its still weighted but not exactly give the number of times I waited for.
I am not sure whats wrong with my code below. Should I do something wrong or I try totally different? Thanks for your answers.
int random_t (int items[], int items_weight[], int number_of_items)
{
double random_weight;
double sum_of_weight = 0;
int i;
/* Calculate the sum of weights */
for (i = 0; i < number_of_items; i++) {
sum_of_weight += items_weight[i];
}
/* Choose a random number in the range [0,1) */
srand(time(NULL));
double g = rand() / ( (double) RAND_MAX + 1.0 );
random_weight = g * sum_of_weight;
/* Find a random number wrt its weight */
int temp_total = 0;
for (i = 0; i < number_of_items; i++)
{
temp_total += items_weight[i];
if (random_weight < temp_total)
{
return items[i];
}
}
return -1; /* Oops, we could not find a random number */
}
I also tried something different (the code is below). It worked for my case, but integer overflow and extensive use of static variables makes it problematic.
If you enter an input array before give NULL and continue to work with it. A little bit similar to strtok() usage.
int random_w(int *arr, int weights[], int size)
{
int selected, i;
int totalWeight;
double ratio;
static long int total;
static long int *eachTotal = NULL;
static int *local_arr = NULL;
static double *weight = NULL;
if (arr != NULL)
{
free(eachTotal);
free(weight);
eachTotal = (long int*) calloc(size, sizeof(long));
weight = (double*) calloc(size, sizeof(double));
total = 0;
totalWeight = 0;
local_arr = arr;
for (i = 0; i < size; i++)
{
totalWeight += weights[i];
}
for (i = 0; i < size; i++)
{
weight[i] = (double)weights[i] / totalWeight;
}
srand(time(NULL));
}
while (1)
{
selected = rand() % size;
ratio = (double)(eachTotal[selected])/(double)(total+1);
if (ratio < weight[selected])
{
total++;
eachTotal[selected]++;
return local_arr[selected];
}
}
}
Is this what you want?
# Weights: one 1, two 2s, three 3s
>>> import random
>>> vals = [1] * 1 + [2] * 2 + [3] * 3
>>> random.shuffle(vals)
>>> vals
[2, 3, 1, 2, 3, 3]
Edit: Whoops, for some reason my mind replaced the C tag with the Python one. Regardless, I think what you want is not "weighted" random number generators, but a shuffle. This ought to help.
When you say you didn't get "exactly" the number of values you expected for each weighted value, how many runs are you talking? If you only did six runs of any random process, I wouldn't expect you to be able to definitively say anything was working or not. Your code may work fine. Try running it a million times and check the results then. Or maybe you actually want what Nathon is talking about, a preweighted list of values, which you can then randomly shuffle and still have the exact weights you're looking for.
You can sample from a multinomial distribution. Your universe of random samples (or "urn of balls in a bucket") is {1, 2, 3} and the probabilities ("weights") of observing each is, respectively, {1/6, 2/6, 3/6}.
For demonstration purposes, a Perl script can give you a list of observations of labeled balls with these probabilities:
#!/usr/bin/perl
use strict;
use warnings;
use Math::Random qw(random_multinomial);
use Data::Dumper;
my $events = 10;
my #probabilities = qw(0.167 0.333 0.5);
my #observations = random_multinomial($events, #probabilities);
print Dumper \#observations;
For 10 events, a single trial will return something like:
$VAR1 = 1;
$VAR2 = 2;
$VAR3 = 7;
This means you have (from this single trial) one 1-labeled event, two 2-labeled events, and seven 3-labeled events.
If you repeat the trial, you may get a different distribution of 1, 2 and 3-labeled events.
You can trivially build a list from this to the equivalent {1, 2, 2, 3, 3, 3, 3, 3, 3, 3} list.
Just randomly shuffle this second list to get your weighted, observed list of random numbers.
If you want to have the sample frequencies be completely deterministic, I think
the way to go is generate an array that has the proper number of occurrences
for each value, then do a random shuffle (which preserves the frequencies)
and take successive elements of the shuffled array as your random sequence.
ok, my answer will sound like a hack - but short or writing your own distribution - maybe you can map an uniform distribution and leverage boost (check out http://www.boost.org/doc/libs/1_44_0/doc/html/boost_random/reference.html#boost_random.reference.distributions)
so following your example:
1 -> 1
2,3 ->2
4,5,6 ->3
7,8,9,10 ->4 (etc...)
then generate random number between 1 and 10 and return the mapped element.
and then use boost's uniform_int distribution to get a number which you then map.
here is an example of generating the numbers; you would then need to map the results:
#include <iostream>
#include <boost/random.hpp>
#include <time.h>
using namespace std;
using namespace boost;
int main ( ) {
uniform_int<> distribution(0, 10) ;
mt19937 engine;
engine.seed(time(NULL));
variate_generator<mt19937, uniform_int<> > myrandom (engine, distribution);
cout << myrandom() << endl;
}

Resources