Error outputting quotient of array and integer - c

Code simulates the rolling of two die 36000 times and outputs "Sum = _; Frequency = _; Percentage = _". Compiled code outputs everything correctly except percentage. "Percentage = 0" when it should output the quotient of "(frequency[calcCount] /36000) * 100" Is this a conflict in data type? How can I properly output the quotient?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SUM_SIZE 36000
#define FREQUENCY_SIZE 13
int main(void){
int rollCount; // counter to loop through 36000 rolls of dice & sums
int calcCount; //counter to loop through frequencies 1-12 of sum calculation
//initialize frequency counters to 0
int frequency[FREQUENCY_SIZE] = {0};
//calculation array
int calculation[SUM_SIZE];
//seed
srand((unsigned)(time(NULL)));
for (rollCount = 1; rollCount <= SUM_SIZE; rollCount++){
//rolling first die
int face1 = (1 + ( rand() % 6));
//rolling second die
int face2 = (1 + ( rand() % 6));
int sum = face1 + face2;
//initializing array elements
calculation[rollCount] = sum;
//for each roll, select value of an element of array calculation
//and use that value as subscript in array frequency to determine
//element to increment (which in this case is the sum frequency)
++frequency[calculation[rollCount]];
}
//displaying results
for (calcCount = 2; calcCount < FREQUENCY_SIZE; calcCount++){
//calculating percentage
int percentage = (frequency[calcCount] /36000) * 100;
printf("Sum = %d; Frequency = %d; Percentage = %d \n", calcCount, frequency[calcCount], percentage);
}
}

When you do a division between two integers, the result will also be an integer and the "exact" result is truncated to fit an integer. Examples:
3/2 -> 1
10/3 -> 3
5/10 -> 0
and when you do
int percentage = (frequency[calcCount] /36000) * 100;
the part frequency[calcCount] /36000 is calculated first. It is a division between two int and it will give the result zero because frequency[calcCount] is less than 36000. Consequently multiplying with 100 still gives zero.
Instead do the multiplication first - like:
int percentage = (100 * frequency[calcCount]) /36000;
Another alternative is to use floating point like:
double percentage = (frequency[calcCount] /36000.0) * 100;
^^^
Notice the .0 to make 36000 a double
but then you need to change the print to use %f
double percentage = (frequency[calcCount] / 36000.0) * 100;
printf("Sum = %d; Frequency = %d; Percentage = %.2f \n", calcCount, frequency[calcCount], percentage);
^^^
Notice this to print the double

Related

Estimating the value of Pi using the Monte Carlo Method

I am writing a C program that will be able to accept an input value that dictates the number of iterations that will be used to estimate Pi.
For example, the number of points to be created as the number of iterations increases and the value of Pi also.
Here is the code I have so far:
#include <stdio.h>
#include <stdlib.h>
main()
{
const double pp = (double)RAND_MAX * RAND_MAX;
int innerPoint = 0, i, count;
printf("Enter the number of points:");
scanf("%d", &innerPoint);
for (i = 0; i < count; ++i){
float x = rand();
float y = rand();
if (x * x + y * y <= 1){
++innerPoint;
}
int ratio = 4 *(innerPoint/ i);
printf("Pi value is:", ratio);
}
}
Help fix my code as I'm facing program errors.
rand() returns an integer [0...RAND_MAX].
So something like:
float x = rand()*scale; // Scale is about 1.0/RAND_MAX
The quality of the Monte Carlo method is dependent on a good random number generator. rand() may not be that good, but let us assume it is a fair random number generator for this purpose.
The range of [0...RAND_MAX] is RAND_MAX+1 different values that should be distributed evenly from [0.0...1.0].
((float) rand())/RAND_MAX biases the end points 0.0 and 1.0 giving them twice the weight of others.
Consider instead [0.5, 1.5, 2.5, ... RAND_MAX + 0.5]/(RAND_MAX + 1).
RAND_MAX may exceed the precision of float so converting rand() or RAND_MAX, both int, to float can incurring rounding and further disturb the Monte Carlo method. Consider double.
#define RAND_MAX_P1 ((double)RAND_MAX + 1.0)
// float x = rand();
double x = ((double) rand() + 0.5)/RAND_MAX_P1;
x * x + y * y can also incur excessive rounding. C has hypot(x,y) for a better precision sqrt(x*x + y*y). Yet here, with small count, it likely makes no observable difference.
// if (x * x + y * y <= 1)
if (hypot(x, y <= 1.0))
I am sure it is not the best solution, but it should do the job and is similar to your code. Use a sample size of at least 10000 to get a value near PI.
As mentioned in the commenter: You should look at the data types of the return values functions give you.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
// Initialize random number generation
srand(time(NULL));
int samples = 10000;
int points_inside =0;
// Read integer - sample size (use at least 10000 to get near PI)
printf("Enter the number of points:");
scanf("%d", &samples);
for (int i = 0; i < samples; ++i){
// Get two numbers between 0 and 1
float x = (float) rand() / (float)RAND_MAX;
float y = (float) rand() / (float)RAND_MAX;
// Check if point is inside
if (x * x + y * y <= 1){
points_inside++;
}
// Calculate current ratio
float current_ratio = 4 * ((float) points_inside / (float) i);
printf("Current value of pi value is: %f \n", current_ratio);
}
}

Logarithm calculator

I'm trying to make a logarithm calculator and got stuck—it doesn't print out a value. The problem may be at lines 15 or 24 or both. How can I make it print the value (all written in C).
Here's the full code:
#include <stdio.h>
#include <stdlib.h>
// Finds base 10 logarithms
int main()
{
float result;
float base = 10.0;
float multiplier = 1.0;
// float counter1 = 0.0;
// float counter2 = 0;
printf("Input result: ");
scanf("%l", result);
// Solves for all results above the base
if(result > base) {
while(result > multiplier) {
multiplier = multiplier * multiplier; // the multiplier has to check non-whole numbers
multiplier += 0.001;
} // division
}
printf("Your exponent is: %l \n", &multiplier);
printf("Hello mathematics!");
return 0;
}
All help appreciated,
Xebiq
you should delete & in printf,and add & in scanf.
printf("Your exponent is: %f \n", multiplier);
scanf("%f", &result);
and use %f in them.
and with base 10 I suggest this function to calculate log:
unsigned int Log2n(unsigned int n)
{
return (n > 1) ? 1 + Log2n(n / 10) : 0;
}
also you should know about Floating-point numbers here:
multiplier += 0.001;
probably exactly 0.001 won't be added to multiplier when I debugged this 0.00100005 was being add to multiplier in my compiler.(which will affect multiplying)
In printf remove '&' and in scanf add '&' before variable.

Is it possible to replace a double number and write the program using only integers in C, with the same output?

Is it possible to write a program like this, using only the integer type and the standard library <stdio.h> in C? The output of the remainder must be displayed as a decimal number with two numbers behind the comma.
#include <stdio.h>
int num1 = 0;
int num2 = 1;
int num3 = 6;
int num4 = 3;
int num5 = 7;
int num6 = 3;
int num7 = 9;
int num8 = 8;
int sum, product, Result;
double division;
int main()
{
sum = num1 + num2 + num3 + num4;
product = num5 * num6 * num7;
Result = ((++product) - (sum++)) * sum;
int Integer_division = Result / (num8+ 1);
int Remainder = Result % (num8+ 1);
double division = Result / (num8+ 1);
printf("Result = %d\n", Result);
printf("Integer division = %d\n", Integer_division);
printf("Remainder = %d\n", Remainder);
printf("Division = %.02f\n", division);
return 0;
}
I was thinking about splitting it into two halves and printing it with a comma in between(%d.%d)
but that sounds like my last resort...
Thanks in advance.
To print floating-point like text from integers requires the sign, while-number part and the fraction part
char *sign = Result<0 ? "-":"";
int whole = abs(Integer_division);
char decimal_point = ','; // behind the comma.
int hundredths = abs(Remainder *100/(num8+ 1)); // Convert fraction to
1/100ths
// now print it
printf("%s%d%c%02d", sign, whole, decimal_point, hundredths);
Yet this displays only a truncated result. To round is work.
The usual way to mimic floating point output using integers it to consider the value as a fraction of 2 integer parts: numerator, denominator that needs scaling (e.g. x100 for .00 display) . For simplicity, assume denominator > 0.
First step is rounding due to finite display precision. Since the next step will involve an integer divide "truncate toward zero" and floating-point like display is usually "round to nearest", code needs to add a signed, unscaled 0.5 or one-half the denominator.
For simplicity, assume denominator > 0 and is odd so we can avoid half-way cases (even more work). Also assume no int overflow to avoid more work.
int numerator = Result;
int denominator = num8+ 1;
int scale = 100; // to print to 0.xx
int scaled_numerator = numerator * scale;
int scaled_half = denominator / 2;
if (scaled_numerator < 0) scaled_half = -scaled_half;
int rounded_scaled_numerator = scaled_numerator + scaled_half;
Now divide
int scaled_value = rounded_scaled_numerator/denominator;
char *sign = scaled_value<0 ? "-":"";
scaled_value = abs(scaled_value);
int whole = scaled_value / scale;
char decimal_point = ',';
int hundredths = scaled_value % scale;
printf("%s%d%c%02d", sign, whole, decimal_point, hundredths);

Implementing equations with very small numbers in C - Plank's Law generating blackbody

I have a problem that, after much head scratching, I think is to do with very small numbers in a long-double.
I am trying to implement Planck's law equation to generate a normalised blackbody curve at 1nm intervals between a given wavelength range and for a given temperature. Ultimately this will be a function accepting inputs, for now it is main() with the variables fixed and outputting by printf().
I see examples in matlab and python, and they are implementing the same equation as me in a similar loop with no trouble at all.
This is the equation:
My code generates an incorrect blackbody curve:
I have tested key parts of the code independently. After trying to test the equation by breaking it into blocks in excel I noticed that it does result in very small numbers and I wonder if my implementation of large numbers could be causing the issue? Does anyone have any insight into using C to implement equations? This a new area to me and I have found the maths much harder to implement and debug than normal code.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
//global variables
const double H = 6.626070040e-34; //Planck's constant (Joule-seconds)
const double C = 299800000; //Speed of light in vacume (meters per second)
const double K = 1.3806488e-23; //Boltzmann's constant (Joules per Kelvin)
const double nm_to_m = 1e-6; //conversion between nm and m
const int interval = 1; //wavelength interval to caculate at (nm)
//typedef structure to hold results
typedef struct {
int *wavelength;
long double *radiance;
long double *normalised;
} results;
int main() {
int min = 100 , max = 3000; //wavelength bounds to caculate between, later to be swaped to function inputs
double temprature = 200; //temprature in kelvin, later to be swaped to function input
double new_valu, old_valu = 0;
static results SPD_data, *SPD; //setup a static results structure and a pointer to point to it
SPD = &SPD_data;
SPD->wavelength = malloc(sizeof(int) * (max - min)); //allocate memory based on wavelength bounds
SPD->radiance = malloc(sizeof(long double) * (max - min));
SPD->normalised = malloc(sizeof(long double) * (max - min));
for (int i = 0; i <= (max - min); i++) {
//Fill wavelength vector
SPD->wavelength[i] = min + (interval * i);
//Computes radiance for every wavelength of blackbody of given temprature
SPD->radiance[i] = ((2 * H * pow(C, 2)) / (pow((SPD->wavelength[i] / nm_to_m), 5))) * (1 / (exp((H * C) / ((SPD->wavelength[i] / nm_to_m) * K * temprature))-1));
//Copy SPD->radiance to SPD->normalised
SPD->normalised[i] = SPD->radiance[i];
//Find largest value
if (i <= 0) {
old_valu = SPD->normalised[0];
} else if (i > 0){
new_valu = SPD->normalised[i];
if (new_valu > old_valu) {
old_valu = new_valu;
}
}
}
//for debug perposes
printf("wavelength(nm) radiance(Watts per steradian per meter squared) normalised radiance\n");
for (int i = 0; i <= (max - min); i++) {
//Normalise SPD
SPD->normalised[i] = SPD->normalised[i] / old_valu;
//for debug perposes
printf("%d %Le %Lf\n", SPD->wavelength[i], SPD->radiance[i], SPD->normalised[i]);
}
return 0; //later to be swaped to 'return SPD';
}
/*********************UPDATE Friday 24th Mar 2017 23:42*************************/
Thank you for the suggestions so far, lots of useful pointers especially understanding the way numbers are stored in C (IEEE 754) but I don't think that is the issue here as it only applies to significant digits. I implemented most of the suggestions but still no progress on the problem. I suspect Alexander in the comments is probably right, changing the units and order of operations is likely what I need to do to make the equation work like the matlab or python examples, but my knowledge of maths is not good enough to do this. I broke the equation down into chunks to take a closer look at what it was doing.
//global variables
const double H = 6.6260700e-34; //Planck's constant (Joule-seconds) 6.626070040e-34
const double C = 299792458; //Speed of light in vacume (meters per second)
const double K = 1.3806488e-23; //Boltzmann's constant (Joules per Kelvin) 1.3806488e-23
const double nm_to_m = 1e-9; //conversion between nm and m
const int interval = 1; //wavelength interval to caculate at (nm)
const int min = 100, max = 3000; //max and min wavelengths to caculate between (nm)
const double temprature = 200; //temprature (K)
//typedef structure to hold results
typedef struct {
int *wavelength;
long double *radiance;
long double *normalised;
} results;
//main program
int main()
{
//setup a static results structure and a pointer to point to it
static results SPD_data, *SPD;
SPD = &SPD_data;
//allocate memory based on wavelength bounds
SPD->wavelength = malloc(sizeof(int) * (max - min));
SPD->radiance = malloc(sizeof(long double) * (max - min));
SPD->normalised = malloc(sizeof(long double) * (max - min));
//break equasion into visible parts for debuging
long double aa, bb, cc, dd, ee, ff, gg, hh, ii, jj, kk, ll, mm, nn, oo;
for (int i = 0; i < (max - min); i++) {
//Computes radiance at every wavelength interval for blackbody of given temprature
SPD->wavelength[i] = min + (interval * i);
aa = 2 * H;
bb = pow(C, 2);
cc = aa * bb;
dd = pow((SPD->wavelength[i] / nm_to_m), 5);
ee = cc / dd;
ff = 1;
gg = H * C;
hh = SPD->wavelength[i] / nm_to_m;
ii = K * temprature;
jj = hh * ii;
kk = gg / jj;
ll = exp(kk);
mm = ll - 1;
nn = ff / mm;
oo = ee * nn;
SPD->radiance[i] = oo;
}
//for debug perposes
printf("wavelength(nm) | radiance(Watts per steradian per meter squared)\n");
for (int i = 0; i < (max - min); i++) {
printf("%d %Le\n", SPD->wavelength[i], SPD->radiance[i]);
}
return 0;
}
Equation variable values during runtime in xcode:
I notice a couple of things that are wrong and/or suspicious about the current state of your program:
You have defined nm_to_m as 10-9,, yet you divide by it. If your wavelength is measured in nanometers, you should multiply it by 10-9 to get it in meters. To wit, if hh is supposed to be your wavelength in meters, it is on the order of several light-hours.
The same is obviously true for dd as well.
mm, being the exponential expression minus 1, is zero, which gives you infinity in the results deriving from it. This is apparently because you don't have enough digits in a double to represent the significant part of the exponential. Instead of using exp(...) - 1 here, try using the expm1() function instead, which implements a well-defined algorithm for calculating exponentials minus 1 without cancellation errors.
Since interval is 1, it doesn't currently matter, but you can probably see that your results wouldn't match the meaning of the code if you set interval to something else.
Unless you plan to change something about this in the future, there shouldn't be a need for this program to "save" the values of all calculations. You could just print them out as you run them.
On the other hand, you don't seem to be in any danger of underflow or overflow. The largest and smallest numbers you use don't seem to be a far way from 10±60, which is well within what ordinary doubles can deal with, let alone long doubles. The being said, it might not hurt to use more normalized units, but at the magnitudes you currently display, I wouldn't worry about it.
Thanks for all the pointers in the comments. For anyone else running into a similar problem with implementing equations in C, I had a few silly errors in the code:
writing a 6 not a 9
dividing when I should be multiplying
an off by one error with the size of my array vs the iterations of for() loop
200 when I meant 2000 in the temperature variable
As a result of the last one particularly I was not getting the results I expected (my wavelength range was not right for plotting the temperature I was calculating) and this was leading me to the assumption that something was wrong in the implementation of the equation, specifically I was thinking about big/small numbers in C because I did not understand them. This was not the case.
In summary, I should have made sure I knew exactly what my equation should be outputting for given test conditions before implementing it in code. I will work on getting more comfortable with maths, particularly algebra and dimensional analysis.
Below is the working code, implemented as a function, feel free to use it for anything but obviously no warranty of any kind etc.
blackbody.c
//
// Computes radiance for every wavelength of blackbody of given temprature
//
// INPUTS: int min wavelength to begin calculation from (nm), int max wavelength to end calculation at (nm), int temperature (kelvin)
// OUTPUTS: pointer to structure containing:
// - spectral radiance (Watts per steradian per meter squared per wavelength at 1nm intervals)
// - normalised radiance
//
//include & define
#include "blackbody.h"
//global variables
const double H = 6.626070040e-34; //Planck's constant (Joule-seconds) 6.626070040e-34
const double C = 299792458; //Speed of light in vacuum (meters per second)
const double K = 1.3806488e-23; //Boltzmann's constant (Joules per Kelvin) 1.3806488e-23
const double nm_to_m = 1e-9; //conversion between nm and m
const int interval = 1; //wavelength interval to calculate at (nm), to change this line 45 also need to be changed
bbresults* blackbody(int min, int max, double temperature) {
double new_valu, old_valu = 0; //variables for normalising result
bbresults *SPD;
SPD = malloc(sizeof(bbresults));
//allocate memory based on wavelength bounds
SPD->wavelength = malloc(sizeof(int) * (max - min));
SPD->radiance = malloc(sizeof(long double) * (max - min));
SPD->normalised = malloc(sizeof(long double) * (max - min));
for (int i = 0; i < (max - min); i++) {
//Computes radiance for every wavelength of blackbody of given temperature
SPD->wavelength[i] = min + (interval * i);
SPD->radiance[i] = ((2 * H * pow(C, 2)) / (pow((SPD->wavelength[i] * nm_to_m), 5))) * (1 / (expm1((H * C) / ((SPD->wavelength[i] * nm_to_m) * K * temperature))));
//Copy SPD->radiance to SPD->normalised
SPD->normalised[i] = SPD->radiance[i];
//Find largest value
if (i <= 0) {
old_valu = SPD->normalised[0];
} else if (i > 0){
new_valu = SPD->normalised[i];
if (new_valu > old_valu) {
old_valu = new_valu;
}
}
}
for (int i = 0; i < (max - min); i++) {
//Normalise SPD
SPD->normalised[i] = SPD->normalised[i] / old_valu;
}
return SPD;
}
blackbody.h
#ifndef blackbody_h
#define blackbody_h
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
//typedef structure to hold results
typedef struct {
int *wavelength;
long double *radiance;
long double *normalised;
} bbresults;
//function declarations
bbresults* blackbody(int, int, double);
#endif /* blackbody_h */
main.c
#include <stdio.h>
#include "blackbody.h"
int main() {
bbresults *TEST;
int min = 100, max = 3000, temp = 5000;
TEST = blackbody(min, max, temp);
printf("wavelength | normalised radiance | radiance |\n");
printf(" (nm) | - | (W per meter squr per steradian) |\n");
for (int i = 0; i < (max - min); i++) {
printf("%4d %Lf %Le\n", TEST->wavelength[i], TEST->normalised[i], TEST->radiance[i]);
}
free(TEST);
free(TEST->wavelength);
free(TEST->radiance);
free(TEST->normalised);
return 0;
}
Plot of output:

Calculate Factorial within a single "for" loop to calculate sum of series

It took me a while conceptual to grasp how to code a loop that would calculate a given series in which a factorial was used.
I coded it--then my teacher told us we had to use a single for loop. I can't seem to grasp how to do something like this. It doesn't make sense how you'd keep the running total of the products across several numbers.
Here is my code; which includes a nested for loop. I really appreciate any and all help.
int main() {
/*init variables*/
int N; //number of terms
float NUMER, DENOM = 1;
float FRAC, sum = 0, x;
/*asks user for value of N*/
printf("Input number of terms: ");
scanf("%i", &N);
/*asks user for value of x*/
printf("Input value of x: ");
scanf("%f", &x);
for (int n = 0; n <= N; n++) {
NUMER = (pow(x, n)); //calculates numerator
for (int fac = 1; fac <= n; fac++) { //calculates factorial using for loop
DENOM = n * fac;
}
if (DENOM <= 0)
printf("\n\nError, dividing by zero.\n\n"); //this is for debugging purposes; disregard
FRAC = NUMER / DENOM; //calculates fraction
sum += FRAC; //running sum of series
}
printf("\nSum of the series is %.1f\n\n", sum); //prints sum of series
return 0;
You want DENOM = n!, so you can just start with DENOM = 1
and update the value inside the loop:
DENOM = 1;
for (int n = 0; n <= N; n++) {
NUMER = (pow(x, n)); //calculates numerator
FRAC = NUMER / DENOM; //calculates fraction
sum += FRAC; //running sum of series
DENOM *= n+1;
}
Instead of computing x^n and n! each time through the outer loop, you can initialize
the quotient to 1.0 before the outer loop, then on each pass through the outer loop,
multiply by x/n to get the next term in the series. This will avoid the need
to call pow(x,n), and use an inner loop to calculate the factorial, each pass through
the outer loop.
If you think about what you would do if calculating a factorial by hand, I think you can figure out how to code this pretty easily.
Lets say you are trying to calculate 11!. Well, you would start at 11, and them multiply by 10. Now you have 110. Now multiply by 9. You have 990. Now multiply by 8...
As you can see, the 11, 10, 9, 8... series is what your for loop is going to be. Just keep your 'current answer' in a variable and keep multiplying it by the number provided by your for loop.
That seems...complicated. Terseness is or can be your friend :D
I don't think it needs to be much more complicated than:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char* argv[] )
{
double limit = 10 ; // how far do we want to go?
double x = 2 ; // some value for X
double xn = 1 ; // by definition, for all X, X^0 is 1
double nf = 1 ; // by convention, 0! is 1
double value = 0 ;
double sum = 0 ;
double n = 0 ;
while ( n < limit )
{
value = xn / nf ; // compute the next element of the series
sum += value ; // add that to the accumulator
xn *= x ; // compute the *next* value for X^n
nf *= (++n) ; // compute the *next* value for N!
}
return 0;
}
You get a more stable answer working the loop in reverse. Many infinite sums numerically come out better summing the smallest terms together first.
f(x,n) = x^0/0! + x^1/1! + x^2/2! + ... + x^n/n!
Let the sum be S(x,n) = x/n
Let the sum of the 2 last terms be S(x,n-1) = x/(n-1) + x/(n-1)*S(x,n)
Let the sum of the 3 last terms be S(x,n-2) = x/(n-2) + x/(n-2)*S(x,n-1)
...
Let the sum of the N last terms be S(x,1) = x/(1) + x/(1)*S(x,1)
double e(double x, unsigned n) {
double sum = 0.0;
while (n > 0) {
sum = x*(1 + sum)/n;
n--;
}
sum += 1.0; // The zero term
return sum;
}
Notice that even if n is large like 1000, and the mathematical answer < DBL_MAX, this loop does not run into floating point overflow so easily.
[edit] But if code must be done in a forward loop, the below calculates each term not as separate products that may overflow, but a unified computation.
double e_forward(double x, unsigned n) {
double sum = 1.0;
double term = 1.0;
for (unsigned i = 1; i <= n; i++) {
term *= x / i;
sum += term;
}
return sum;
}

Resources