C - Random value +/- from previous value - c

I was trying to write some code in C to simulate temperature fluctuations +/- 4 from the previous value, however I'm getting some wild jumps in either direction.
The program is multi-threaded, however, even testing in isolation produces the same wrong results.
I've tried several variations on the code, thinking that it had to do with how the code was evaluating, but my errors but they all end up the same. My code is as follows:
int main(){
srand(1); //Just for testing and predictability of outcome
//short int temp = 20 + rand() / (RAND_MAX / 30 - 20 + 1) + 1; Initially I was initialising it at a random value between 20-30, but chose 20 for testing purposes
short int temp = 20;
short int new_temp, last_temp, new_min, new_max;
last_temp = temp;
for(int i = 0; i < 20; i++){
//last_temp = temp; At first I believed it was because last_temp wasn't being reassigned, however, this doesn't impact the end result
new_min = last_temp - 4;
new_max = last_temp + 4;
//new_temp = (last_temp-4) + rand() / (RAND_MAX / (last_temp + 4) - (last_temp - 4) + 1) + 1; I Also thought this broke because they last_temp was being changed with the prior math in the equations. Still no impact
new_temp = new_min + rand() / (RAND_MAX / new_max - new_min + 1) + 1;
printf("Temperature is %d\n", new_temp);
}
return 0;
}
Produces results like this.
Temperature is 37
Temperature is 26
Temperature is 35
Temperature is 36
Temperature is 38
As you can see, the first temperature reading should be within the range of 16-24, however it increases by 17 to 37, and I can't figure out why. Any insight would be appreciated. In the alternative, can anyone provide me with a clean way to simulate a random +/- without having to use a lot of embedded if statements?

There are 2 issues in this code:
rand() usage
last_temp value is not updating in each iteration
rand usage
rand() returns a value between 0 and RAND_MAX. You want to limit this value in [0,8] and add it to new_min, so that new_temp is limited in [last_temp-4,last_temp+4], ie [new_min,new_min+8].
To do that, you use % operator. By doing rand() % 9, you limit your random value between 0 and 8. So, the new_temp value should be: new_temp = new_min + rand() % 9.
last_temp update
You need to update the last_temp value after you assign your new_temp value like this:
new_temp = new_min + rand() % 9;
last_temp = new_temp;
So, you for loop should look like this in the end:
for(int i = 0; i < 20; i++){
new_min = last_temp - 4;
new_max = last_temp + 4;
new_temp = new_min + rand() % 9;
last_temp = new_temp;
printf("Temperature is %d\n", new_temp);
}
And the code can be minimized to this:
int main() {
srand(1); //Just for testing and predictability of outcome
short int temp = 20; //or 20 + rand()%11 for values in [20,30] range
for(int i = 0; i < 20; i++) {
temp += -4 + rand() % 9;
printf("Temperature is %hd\n", temp);
}
return 0;
}
with an outcome of:
Temperature is 23
Temperature is 25
Temperature is 22
Temperature is 21
Temperature is 18
Temperature is 21
Temperature is 19
Temperature is 19
Temperature is 16
Temperature is 17
Temperature is 15
Temperature is 14
Temperature is 12
Temperature is 11
Temperature is 10
Temperature is 12
Temperature is 12
Temperature is 10
Temperature is 10
Temperature is 6

Related

How to add product digits rather than products themselves in C?

I am trying to finish an assignment in C for the CS50 course in which I must implement Luhn's algorithm to validate a credit card number. Here is a quick example to elaborate:
credit card number: 4003600000000014.
Now for every other digit, starting with the number’s second-to-last digit:
1-0-0-0-0-6-0-4
Let’s multiply each of the digits by 2:
1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2
That gives us:
2 + 0 + 0 + 0 + 0 + 12 + 0 + 8
Now let’s add those products’ digits (i.e., not the products themselves) together:
2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13
Now let’s add that sum (13) to the sum of the digits that weren’t multiplied by 2 (starting from the end):
13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20
Yup, the last digit in that sum (20) is a 0, so the number is valid.
I figured out how to extract each number in the credit card individually (I know my way is boring and probably not practical), so the next step is to multiply every other number by two and add (the products' digits, not the digits themselves) and this is what I need help of how to do it?
MY code:
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
long credit_card_number;
do
{
credit_card_number = get_long("Enter your credit card number: ");
}
while (credit_card_number < 1 || credit_card_number > 9999999999999999);
//American Express uses 15-digit numbers. American Express numbers start with 34 or 37
//MasterCard uses 16-digit numbers. MasterCard numbers start with 51, 52, 53, 54, or 55.
//Visa uses 13- and 16-digit numbers. Visa numbers start with 4.
// checksum
long last_number;
long credit_card_without_last_number;
long second_to_last_number;
long credit_card_without_second_number;
long third_number;
long credit_card_without_third_number;
long fourth_number;
long credit_card_without_fourth_number;
long fifth_number;
long credit_card_without_fifth_number;
long sixth_number;
long credit_card_without_sixth_number;
long seventh_number;
long credit_card_without_seventh_number;
long eighth_number;
long credit_card_without_eighth_number;
long ninth_number;
long credit_card_without_ninth_number;
long tenth_number;
long credit_card_without_tenth_number;
long eleventh_number;
long credit_card_without_eleventh_number;
long twelfth_number;
long credit_card_without_twelfth_number;
long thirteenth_number;
long credit_card_without_thirteenth_number;
long fourteenth_number;
long credit_card_without_fourteenth_number;
long fifteenth_number;
long credit_card_without_fifteenth_number;
long sixteenth_number;
long multiply_digits;
//separating each number starting from the last (right)in its own variable.
last_number = credit_card_number % 10;
credit_card_without_last_number = credit_card_number / 10;
second_to_last_number = credit_card_without_last_number % 10;
credit_card_without_second_number = credit_card_without_last_number / 10;
third_number = credit_card_without_second_number % 10;
credit_card_without_third_number = credit_card_without_second_number / 10;
fourth_number = credit_card_without_third_number % 10;
credit_card_without_fourth_number = credit_card_without_third_number / 10;
fifth_number = credit_card_without_fourth_number % 10;
credit_card_without_fifth_number = credit_card_without_fourth_number / 10;
sixth_number = credit_card_without_fifth_number % 10;
credit_card_without_sixth_number = credit_card_without_fifth_number / 10;
seventh_number = credit_card_without_sixth_number % 10;
credit_card_without_seventh_number = credit_card_without_sixth_number / 10;
eighth_number = credit_card_without_seventh_number % 10;
credit_card_without_eighth_number = credit_card_without_seventh_number / 10;
ninth_number = credit_card_without_eighth_number % 10;
credit_card_without_ninth_number = credit_card_without_eighth_number / 10;
tenth_number = credit_card_without_ninth_number % 10;
credit_card_without_tenth_number = credit_card_without_ninth_number / 10;
eleventh_number = credit_card_without_tenth_number % 10;
credit_card_without_eleventh_number = credit_card_without_tenth_number / 10;
twelfth_number = credit_card_without_eleventh_number % 10;
credit_card_without_twelfth_number = credit_card_without_eleventh_number / 10;
thirteenth_number = credit_card_without_twelfth_number % 10;
credit_card_without_thirteenth_number = credit_card_without_twelfth_number / 10;
fourteenth_number = credit_card_without_thirteenth_number % 10;
credit_card_without_fourteenth_number = credit_card_without_thirteenth_number / 10;
fifteenth_number = credit_card_without_fourteenth_number % 10;
credit_card_without_fifteenth_number = credit_card_without_fourteenth_number / 10;
sixteenth_number = credit_card_without_fifteenth_number % 10;
//Here I need the help to multiply these numbers by two and then add each product's
//digits to the rest of the unused numbers.
multiply_digits = (second_to_last_number*2)+(fourth_number*2)+(sixth_number*2)+(eighth_number*2)+(tenth_number*2)+(twelfth_number*2)+(fourteenth_number*2)+(sixteenth_number*2);
}
Try doing this instead
int main(){
long cNo = 4003600000000014;
int arr[16];
for(int i=0; i<16; i++){
arr[15-i] = cNo % 10;
cNo /= 10;
}
int multipliedSum = 0;
for(int i=0; i<16; i++){
if(i%2==1)
multipliedSum += arr[i];
else{
if(arr[i]*2<10){
multipliedSum += (arr[i]*2);
}else{
int num = arr[i]*2;
while(num){
multipliedSum += num%10;
num/=10;
}
}
}
}
printf("valid = %s\n",multipliedSum%10==0?" True": " False");
}
You will get the following
valid = True
A general algorithm for adding digits (assuming an integer type):
Initialize your sum to 0: sum = 0
Extract the lowest digit from the number using the % modulus operator: digit = number % 10
Add the value of that digit to the sum: sum += digit (shorthand for sum = sum + digit)
Divide the number by 10: number /= 10 (shorthand for number = number / 10
If the number is non-zero after dividing by 10, go back to 2
End
The modulus operator % returns the integer remainder of an integer division - 123 / 10 == 12 rem 3. So the remainder of dividing the number by 10 is the least significant decimal digit of the number. Notice that integer division gives you an integer result - 123 / 10 == 12, not 12.3.
You'll want to put this in a separate function, so you can write something like
int sumdig( int v )
{
...
}
int main( void )
{
int value = 123;
int sum = sumdig( value ); // sumdig will return 1 + 2 + 3, or 6
...
}
When you find yourself creating a bunch of separate variables of the same type with the same name except for some tacked-on ordinal (var1, var2, var3 or first_thing, second_thing, third_thing), that's a real strong hint you want to use an array. You can use an array to store the individual digits of your card number:
int number[16];
and use the % 10 method as described above to extract the individual digits:
long tmp = credit_card_number; // use a temporary so we preserve the original card number
for ( int i = 0; i < 16; i++ )
{
number[i] = tmp % 10;
tmp /= 10;
}
This means that the least significant (rightmost) card number digit will be stored in number[0] and the most significant (leftmost) card number digit will be stored in number[15], so be aware of that. For the purposes of validating the number it doesn't matter, but if you want to display the contents of the array you'll have to take that into account.
Using an array makes it easier to extract subsets of digits:
for ( int i = 1; i < 16; i += 2 ) // hit every other element starting at element 1
{
number[i] *= 2; // multiply these digits by 2
}
That loop above executes the "1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2" portion of your algorithm.
You should be able to figure out the rest from there. Hope this helps.
Hint: to extract one digit from a number, mod it by 10.
So say that you want to figure out the sum of the digits of a number, say 123456, you will do the following:
(pseudocode)
number=123456;
sum=0;
loop if number is not 0{
sum+=number % 10;
number-=number % 10;
number=(int)(number/10);
}
Now try to implement it as a function, say digit(), and when you are trying to add some numbers digit-wise, say 123 and 456, just do digit(123)+digit(456) instead.

rand() function behavior

I'm learning about the rand() function in C, as I want to use it to generate a random number in a range. However, I have a question about a part of the algorithm below.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
const MAX = 20, MIN = 1;
srand(time(NULL));
int randNumber = rand() % (MAX - MIN + 1) + MIN;
printf("%d", randNumber);
// yeu cau nhap so
int duDoan;
printf("Moi ban du doan con so:");
scanf("%d", &duDoan);
// chay vong lap kiem tra
while(duDoan != randNumber) {
printf("Ban da sai. Moi nhap lai:");
scanf("%d", &duDoan);
}
printf("Ban da nhap dung. Dap an la: %d ", randNumber);
return 0;
}
What confuses me here is why we have to add + MIN in this line:
rand() % (MAX - MIN + 1) + MIN;
If I leave it, what will the result be?
rand() is a number between 0 and RAND_MAX.
rand() % n is a number between 0 and n - 1. If you want a value from 0 to n, then you need rand() % (n+1).
In your example (MAX - MIN + 1) is the span of integer values to generate, while MIN is the lower value. So for example where:
MIN = -10
MAX = 10
the span n :
n = (MAX - MIN + 1) = 21
so that:
rand() % n
yields values from 0 to 20, and
rand() % n - MIN
is -10 to +10. Without the +1, it would incorrectly be -10 to +9.
Note that where a statistically high quality random number is required restricting the span by the use of % is flawed and will introduce a bias when n is not a factor of RAND_MAX + 1. In that case (int)(n * ((double)rand() / (double)RAND_MAX)) is a better solution, so you would have:
int randNumber = (int)((MAX - MIN) * ((double)rand() /
(double)RAND_MAX)) + MIN ;
Note there is no +1 here because the range of (double)rand() / (double)RAND_MAX is 0 to 1, so multiplying by n gives 0 to n inclusive.

C , execution at terminal gives error "Killed : 9"

Am doing this coursework in a very tedious way I know , but it is due tomorrow so I will just have to stick with this way for now because I dont have much time to figure out another. what this code does it it takes a 10 digit number and divides it into 10 digits, checks for every possibility from 1 to this number , if the sum of the 10 digits equals 37 , if it is , it increments a counter giving out the total number of numbers that there digits add up to 37. Problem is with such large number I guess something wrong with the memory allocation and this stuff happens, when I run it on the macOS terminal it gives me the error "Killed : 9" (after some time ofc)
Here is my source code ( In C Language):
#include<stdio.h>
#include<stdlib.h>
int main()
{
long long *counter = malloc(9999999999 * sizeof(*counter)); // size of array should be up to 9999999999
long long counter2 = 1; // long long because counter 2 goes up to 10 digits , MAX 9999999999
int FirstDigit, secondDigit ,ThirdDigit , fourthdigit, fifthdigit , sixthdigit,seventhdigit,eightdigit,ninthdigit,tenthdigit ;
unsigned long z2 , z3 ,c , z1 , z4 , z5,z6 ,z7; // max 9 digits
unsigned long count = 0; // max 9 digits
for (long long i = 1 ; i<9999999999 ; i++)
{
counter[i] = counter2; // appends number to array
counter2 += 1; // increments counter for next append
FirstDigit = counter[i] / 1000000000;
z1= counter[i] / 100000000;
secondDigit = z1 % 10;
c = counter[i] / 10000000;
ThirdDigit = c % 10 ; // a holds 3rd digit
z3 = counter[i] / 1000000;
fourthdigit = z3 % 10; // d holds 2nd digit
z2 = counter[i] /100000;
fifthdigit = z2 % 10;
z4 = counter[i] / 10000;
sixthdigit = z4 % 10;
z5 = counter[i] / 1000;
seventhdigit = z5 % 10;
z6 = counter[i] / 100;
eightdigit = z6 % 10;
z7 = counter[i] / 10;
ninthdigit = z7 % 10;
tenthdigit = counter[i] % 10;
if( (FirstDigit + secondDigit + ThirdDigit + fourthdigit + fifthdigit + sixthdigit + seventhdigit +eightdigit + ninthdigit + tenthdigit) == 37 )
{
count+= 1;
}
}
printf("%lu\n", count );
}
After this
long long *counter = malloc(9999999999 * sizeof(*counter));
put
printf("Address returned by malloc: %p\n", (void*) counter);
You'll see that it returns 0, because your system can't allocate that much memory, and now when you try to write to that address you'll get a segfault. Always check the return codes from your mallocs.
The problem is that reserving several Gigabytes of memory for your application is likely to fail, indicated in that counter will be NULL. You could easily check this by writing if(counter==NULL) { printf("could not allocate memory."); return 1; }. If you do not check this, you will access memory which you are not allowed to access, yielding undefined behaviour, very often yielding segfaults.
BTW: for just calculating the sums of the digits, you do not need to actually store all the numbers you want to check in memory. So the complete counter-array is not needed. Remove the malloc and replace counter[i] with i in your loop:
for (long long i = 1 ; i<9999999999 ; i++)
{
FirstDigit = i / 1000000000;
z1= i / 100000000;
secondDigit = z1 % 10;
...
}

Calculate the function sin()

For my studies, I have to code an algorithm to calculate sin() with this function:
However, in my algorithm, I have to keep the value of X between 0 and Pi/2. So, I wrote my algorithm but all the results are wrong.
Here is my code:
double sinX(double x){
double resultat = 0;
int i;
if(x < 0 || x > M_PI_2)
x = fmod(x,M_PI_2);
for(i = 1;i<=30;i++){
resultat += -1 * ((x*x)/(2*i*(2*i+1)))*(pow(-1,i-1))*((pow(x,2*i-1))/(factorielle(2*i-1)));
}
return resultat;
}
I didn't find the reason. Can you help me?
Here the are few values of X and the result with fmod
1 / 1
2 / 0.429204
3 / 1.4292
4 / 0.858407
5 / 0.287611
6 / 1.28761
7 / 0.716815
8 / 0.146018
9 / 1.14602
10 / 0.575222
11 / 0.00442571
12 / 1.00443
13 / 0.433629
14 / 1.43363
15 / 0.862833
16 / 0.292037
17 / 1.29204
18 / 0.72124
19 / 0.150444
20 / 1.15044
and the result with the algorithm
1 / -0.158529
2 / -0.0130568
3 / -0.439211
4 / -0.101605
5 / -0.00394883
6 / -0.327441
7 / -0.0598281
8 / -0.000518332
9 / -0.234888
10 / -0.0312009
11 / -1.44477e-008
12 / -0.160572
13 / -0.0134623
14 / -0.443022
15 / -0.103145
16 / -0.00413342
17 / -0.330639
18 / -0.0609237
19 / -0.000566869
20 / -0.237499
Here is my "factorielle" definition
double factorielle(double x){
double resultat = 1;
int i;
if(x != 0){
for (i=2;i<=x;i++)
{
resultat *= i;
}
}
else{
resultat = 1;
}
return resultat;
}
And values :
1 / 1
2 / 2
3 / 6
4 / 24
5 / 120
6 / 720
7 / 5040
8 / 40320
9 / 362880
10 / 3.6288e+006
11 / 3.99168e+007
12 / 4.79002e+008
13 / 6.22702e+009
14 / 8.71783e+010
15 / 1.30767e+012
16 / 2.09228e+013
17 / 3.55687e+014
18 / 6.40237e+015
19 / 1.21645e+017
20 / 2.4329e+018
You're misunderstanding the purpose of the second formula you show. The idea is that you use that formula to compute each term in the sum from the preceding term, saving you from the need to use any pow or factorial calls.
#include <stdio.h>
double sinX(double x) {
double term, total_so_far;
int i;
term = x; /* First term in the expansion. */
total_so_far = 0.0;
for (i = 1; i <= 30; i++) {
/* Add current term to sum. */
total_so_far += term;
/* Compute next term from the current one. */
term *= -(x * x) / (2*i) / (2*i + 1);
}
return total_so_far;
}
int main(void) {
/* testing */
double x;
int i;
for (i = 0; i <= 10; i++) {
x = i / 10.0;
printf("sin(%f) is %f\n", x, sinX(x));
}
return 0;
}
And the results of running this code, on my machine:
sin(0.000000) is 0.000000
sin(0.100000) is 0.099833
sin(0.200000) is 0.198669
sin(0.300000) is 0.295520
sin(0.400000) is 0.389418
sin(0.500000) is 0.479426
sin(0.600000) is 0.564642
sin(0.700000) is 0.644218
sin(0.800000) is 0.717356
sin(0.900000) is 0.783327
sin(1.000000) is 0.841471
That should give you reasonable results for the range 0 to pi / 2. Outside that range you'll need to be a bit cleverer about the reduction you're using: simply reducing modulo pi / 2 won't give correct results. (Hint: it's safe to reduce modulo 2 * pi, since the sin function is periodic with period 2 * pi. Now use symmetries of the sin function to reduce to the range 0 to pi / 2.)
EDIT An explanation of why the current code is giving incorrect results: apart from the flawed reduction step, in your sum you start with the term i = 1. But the first term should be for i = 0 (that's the x term, while the i=1 term is the -x^3 / 3! term). A quick and dirty fix is to remove the reduction step, and to initialise your resultat variable to x rather than 0. That should give you good results for small x, and then you can figure out how to replace the reduction step. I'd be surprised if you were really intended to compute the answer using explicit factorial and power calls, though - I'm almost sure that you're expected to compute each term from the preceding one as described above.
There are two problems with your code:
sin(x+k*π/2) does not necessarily equal sin(x)
Your expression for the term is a little bit messed up. The instructions seem to suggest that you calculate the next term in the series from the previous term. Start with the value for i=0 and then use the equation in your question to compute the next term in each iteration.
Finally, I followed yours indications. Here is my final code :
double sinX(double x)
{
double result = 1.0;
double term_i = 1.0;
int i = 2;
x = fmod(x, 2*M_PI);
for(i = 2; i<= 30; i+=2)
{
term_i = (-term_i * (x*x)) / (i*(i+1));
result += term_i;
}
return x * result;
}
Idea about the number of terms with OP's posted answer.
As long as one performs some range limitation first, like fmod(), the number of terms needed can be reasonably determined dynamically. (Uses 1 to 23 iterations for x: 0 to 2*pi.)
double sinX1(double x)
{
double result = 1.0;
double term_i = 1.0;
int i = 2;
x = fmod(x, 2*M_PI);
// for(i = 2; i<= 30; i+=2)
for(i = 2; ((1.0 + term_i) != 1.0); i+=2)
{
term_i = (-term_i * (x*x)) / (i*(i+1));
result += term_i;
}
return x * result;
}

Initialization of an array using rand() function

I want to initialize my input random array to find the fft of the size of the input array. I want that the input array should contain complex numbers(e.g a+jb) which has to be done using rand() in c. I am trying to do it like this:
sint16 min= Some value a;
sint16 max= Some value b;
sint32 array[1536];
uint16 i;
for(i=0; i<1536; i++) {
r= rand()%(max+min+1)+min;
array[i]=r;
}
but it is not producing the results I need.
Consider how max + min + 1 will vary when you plug in different values of max and min:
max = 10, min = 0 => 10 + 0 + 1 = 11
max = 30, min = 20 => 30 + 20 + 1 = 51
Now, the actual range is the same in those two examples, right?
So, you equation should be:
r = rand() % (max - min + 1);
Note the subtraction, to compute distance from min to max (assuming max > min).

Resources