Track first digit during a long multiplication in c - c

I have an array of integer element range up to 10^5, and I have to find the first element after the total multiplication.
Example:
Array : 2,4,6,7
multiplication result: 336 and the first element is 3.
Obviously I cannot multiply the elements with the range up to 10^5.
How can I track only the first digit during multiplication?

We can also find the first digit with another method.
Suppose p be the final value after multiplying all the elements.
So, we have to find
P = a[0]*a[1]*a[2]*a[3]*.......*a[n-1]
for n sized array then we can take log with base 10 on both the side after that our expression changes to
log(p) = log(a[i])+log(a[1])+log(a[2])+.....+log(a[n-1])
Now, to find the first digit we have to get the fractional part of this variable sum which can be done in this way
frac = sum - (integer)sum
and at the last step calculate the 10^frac and convert it to the integer value which is our required first digit.
This algorithm is better in comparison to time complexity.
int getFirstDigit(long a[], long n) {
double p;
for(int i=0;i<n;i++) {
p = p+log10(a[i]);
}
double frac = p - (long)p;
int firdig = (int)pow(10,frac);
return firdig;
}

In c or c++ make integer data type as long double such that first digit of number is before decimal point and rest are after decimal point.
Above can be done as follows:-
long double GetFraction(int number){
int length = (int) log(number) + 1; // this will give number of digits in given number. And log is log base 10.
long double fraction = (long double) number / (10^(length - 1);
return fraction;
}
Example :-
Let number = 12345
length = log(12345) + 1 = 5;
fraction = (long double) 12345 / (10^4) = 1.2345
Now for all integers in array find fraction as mention above and multiply them as follow:-
int GetFirstDigit(int arr[] , int size){
if(size == 0)
return 0;
long double firstDigit = 1.0;
for(int i = 0 ; i < size ; i++){
firstDigit = firstDigit*GetFraction(arr[i]);
if(firstDigit >= 10.00) // You have to shorten your number otherwise it will same as large multiplication and will overflow.
firstDigit/=10;
}
return (int) firstDigit;
}
Disclaimer:- This is my approach and I don't have any formal proof about accuracy of result. But I have verified result for integer up to 10^9 and array size up to 10^5

Please donot forget to note that this is just an attempt to make you understand the logic and that you need to make changes in the code as per your requirement. I strongly suggest you make this a subroutine in your program and parse the arguments to it from the main thread in your program.
#include <stdio.h>
void main()
{
int num1, num2;
printf("Enter ur lovely number:\n");
scanf("%d",&num1);
num2=num1;
while(num2)
{
num2=num2/10;
if(num2!=0)
num1=num2;
}
printf("The first digit of the lovely number is %d !! :P\n ",num1);
}

Try this approach,
Take integer as input let us say int x1, now copy this in a double let us say double x2, and suppose you have previous product as double y, initially y = 1 . now use this loop,
while(x1!<10){
x1 = x1/10;
x2 = x2/10; //this will make double in standard form x*10^y without 10^y part
}
ex x1 = 52, then x2 will be converted to 5.2.
Now let us assume y = 3 and x is 5.2.
then product now is 15.6, again reduce this to 1.56 and repeat the process. in the end you will have the only digit before the decimal as the first digit of the product of all the numbers.

Related

How to compute the digits of an irrational number one by one?

I want to read digit by digit the decimals of the sqrt of 5 in C.
The square root of 5 is 2,23606797749979..., so this'd be the expected output:
2
3
6
0
6
7
9
7
7
...
I've found the following code:
#include<stdio.h>
void main()
{
int number;
float temp, sqrt;
printf("Provide the number: \n");
scanf("%d", &number);
// store the half of the given number e.g from 256 => 128
sqrt = number / 2;
temp = 0;
// Iterate until sqrt is different of temp, that is updated on the loop
while(sqrt != temp){
// initially 0, is updated with the initial value of 128
// (on second iteration = 65)
// and so on
temp = sqrt;
// Then, replace values (256 / 128 + 128 ) / 2 = 65
// (on second iteration 34.46923076923077)
// and so on
sqrt = ( number/temp + temp) / 2;
}
printf("The square root of '%d' is '%f'", number, sqrt);
}
But this approach stores the result in a float variable, and I don't want to depend on the limits of the float types, as I would like to extract like 10,000 digits, for instance. I also tried to use the native sqrt() function and casting it to string number using this method, but I faced the same issue.
What you've asked about is a very hard problem, and whether it's even possible to do "one by one" (i.e. without working space requirement that scales with how far out you want to go) depends on both the particular irrational number and the base you want it represented in. For example, in 1995 when a formula for pi was discovered that allows computing the nth binary digit in O(1) space, this was a really big deal. It was not something people expected to be possible.
If you're willing to accept O(n) space, then some cases like the one you mentioned are fairly easy. For example, if you have the first n digits of the square root of a number as a decimal string, you can simply try appending each digit 0 to 9, then squaring the string with long multiplication (same as you learned in grade school), and choosing the last one that doesn't overshoot. Of course this is very slow, but it's simple. The easy way to make it a lot faster (but still asymptotically just as bad) is using an arbitrary-precision math library in place of strings. Doing significantly better requires more advanced approaches and in general may not be possible.
As already noted, you need to change the algorithm into a digit-by-digit one (there are some examples in the Wikipedia page about the methods of computing of the square roots) and use an arbitrary precision arithmetic library to perform the calculations (for instance, GMP).
In the following snippet I implemented the before mentioned algorithm, using GMP (but not the square root function that the library provides). Instead of calculating one decimal digit at a time, this implementation uses a larger base, the greatest multiple of 10 that fits inside an unsigned long, so that it can produce 9 or 18 decimal digits at every iteration.
It also uses an adapted Newton method to find the actual "digit".
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <gmp.h>
unsigned long max_ul(unsigned long a, unsigned long b)
{
return a < b ? b : a;
}
int main(int argc, char *argv[])
{
// The GMP functions accept 'unsigned long int' values as parameters.
// The algorithm implemented here can work with bases other than 10,
// so that it can evaluate more than one decimal digit at a time.
const unsigned long base = sizeof(unsigned long) > 4
? 1000000000000000000
: 1000000000;
const unsigned long decimals_per_digit = sizeof(unsigned long) > 4 ? 18 : 9;
// Extract the number to be square rooted and the desired number of decimal
// digits from the command line arguments. Fallback to 0 in case of errors.
const unsigned long number = argc > 1 ? atoi(argv[1]) : 0;
const unsigned long n_digits = argc > 2 ? atoi(argv[2]) : 0;
// All the variables used by GMP need to be properly initialized before use.
// 'c' is basically the remainder, initially set to the original number
mpz_t c;
mpz_init_set_ui(c, number);
// At every iteration, the algorithm "move to the left" by two "digits"
// the reminder, so it multplies it by base^2.
mpz_t base_squared;
mpz_init_set_ui(base_squared, base);
mpz_mul(base_squared, base_squared, base_squared);
// 'p' stores the digits of the root found so far. The others are helper variables
mpz_t p;
mpz_init_set_ui(p, 0UL);
mpz_t y;
mpz_init(y);
mpz_t yy;
mpz_init(yy);
mpz_t dy;
mpz_init(dy);
mpz_t dx;
mpz_init(dx);
mpz_t pp;
mpz_init(pp);
// Timing, for testing porpuses
clock_t start = clock(), diff;
unsigned long x_max = number;
// Each "digit" correspond to some decimal digits
for (unsigned long i = 0,
last = (n_digits + decimals_per_digit) / decimals_per_digit + 1UL;
i < last; ++i)
{
// Find the greatest x such that: x * (2 * base * p + x) <= c
// where x is in [0, base), using a specialized Newton method
// pp = 2 * base * p
mpz_mul_ui(pp, p, 2UL * base);
unsigned long x = x_max;
for (;;)
{
// y = x * (pp + x)
mpz_add_ui(yy, pp, x);
mpz_mul_ui(y, yy, x);
// dy = y - c
mpz_sub(dy, y, c);
// If y <= c we have found the correct x
if ( mpz_sgn(dy) <= 0 )
break;
// Newton's step: dx = dy/y' where y' = 2 * x + pp
mpz_add_ui(yy, yy, x);
mpz_tdiv_q(dx, dy, yy);
// Update x even if dx == 0 (last iteration)
x -= max_ul(mpz_get_si(dx), 1);
}
x_max = base - 1;
// The actual format of the printed "digits" is up to you
if (i % 4 == 0)
{
if (i == 0)
printf("%lu.", x);
putchar('\n');
}
else
printf("%018lu", x);
// p = base * p + x
mpz_mul_ui(p, p, base);
mpz_add_ui(p, p, x);
// c = (c - y) * base^2
mpz_sub(c, c, y);
mpz_mul(c, c, base_squared);
}
diff = clock() - start;
long int msec = diff * 1000L / CLOCKS_PER_SEC;
printf("\n\nTime taken: %ld.%03ld s\n", msec / 1000, msec % 1000);
// Final cleanup
mpz_clear(c);
mpz_clear(base_squared);
mpz_clear(p);
mpz_clear(pp);
mpz_clear(dx);
mpz_clear(y);
mpz_clear(dy);
mpz_clear(yy);
}
You can see the outputted digits here.
Your title says:
How to compute the digits of an irrational number one by one?
Irrational numbers are not limited to most square roots. They also include numbers of the form log(x), exp(z), sin(y), etc. (transcendental numbers). However, there are some important factors that determine whether or how fast you can compute a given irrational number's digits one by one (that is, from left to right).
Not all irrational numbers are computable; that is, no one has found a way to approximate them to any desired length (whether by a closed form expression, a series, or otherwise).
There are many ways numbers can be expressed, such as by their binary or decimal expansions, as continued fractions, as series, etc. And there are different algorithms to compute a given number's digits depending on the representation.
Some formulas compute a given number's digits in a particular base (such as base 2), not in an arbitrary base.
For example, besides the first formula to extract the digits of π without computing the previous digits, there are other formulas of this type (known as BBP-type formulas) that extract the digits of certain irrational numbers. However, these formulas only work for a particular base, not all BBP-type formulas have a formal proof, and most importantly, not all irrational numbers have a BBP-type formula (essentially, only certain log and arctan constants do, not numbers of the form exp(x) or sqrt(x)).
On the other hand, if you can express an irrational number as a continued fraction (which all real numbers have), you can extract its digits from left to right, and in any base desired, using a specific algorithm. What is more, this algorithm works for any real number constant, including square roots, exponentials (e and exp(x)), logarithms, etc., as long as you know how to express it as a continued fraction. For an implementation see "Digits of pi and Python generators". See also Code to Generate e one Digit at a Time.

C - digits in a long

I'm new to programming and stuck in a problem.
I have a long variable of any length.
I want to extract any number of digits of this number.
An Example: Number = 135678256 and I want the first two digits, here 13.
I added some pseudo-code, which shall represent my first idea.
int digits(long n){
int x = n / (10^ length(long n)) ;
int y = n / (10^(length(long n)-1)) ;
y = x-y;
return x,y};
length is a function that returns the length of Number.
How to change my code efficiently to get the fourth and fifth digits?
Thanks a lot!

taylor series with error at most 10^-3

I'm trying to calculate the the taylor series of cos(x) with error at most 10^-3 and for all x ∈ [-pi/4, pi/4], that means my error needs to be less than 0.001. I can modify the x +=in the for loop to have different result. I tried several numbers but it never turns to an error less than 0.001.
#include <stdio.h>
#include <math.h>
float cosine(float x, int j)
{
float val = 1;
for (int k = j - 1; k >= 0; --k)
val = 1 - x*x/(2*k+2)/(2*k+1)*val;
return val;
}
int main( void )
{
for( double x = 0; x <= PI/4; x += 0.9999 )
{
if(cosine(x, 2) <= 0.001)
{
printf("cos(x) : %10g %10g %10g\n", x, cos(x), cosine(x, 2));
}
printf("cos(x) : %10g %10g %10g\n", x, cos(x), cosine(x, 2));
}
return 0;
}
I'm also doing this for e^x too. For this part, x must in [-2,2] .
float exponential(int n, float x)
{
float sum = 1.0f; // initialize sum of series
for (int i = n - 1; i > 0; --i )
sum = 1 + x * sum / i;
return sum;
}
int main( void )
{
// change the number of x in for loop so you can have different range
for( float x = -2.0f; x <= 2.0f; x += 1.587 )
{
// change the frist parameter to have different n value
if(exponential(5, x) <= 0.001)
{
printf("e^x = %f\n", exponential(5, x));
}
printf("e^x = %f\n", exponential(5, x));
}
return 0;
}
But whenever I changed the number of terms in the for loop, it always have an error that is greater than 1. How am I suppose to change it to have errors less than 10^-3?
Thanks!
My understanding is that to increase precision, you would need to consider more terms in the Taylor series. For example, consider what happens when
you attempt to calculate e(1) by a Taylor series.
$e(x) = \sum\limits_{n=0}^{\infty} frac{x^n}{n!}$
we can consider the first few terms in the expansion of e(1):
n value of nth term sum
0 x^0/0! = 1 1
1 x^1/1! = 1 2
2 x^2/2! = 0.5 2.5
3 x^3/3! = 0.16667 2.66667
4 x^4/4! = 0.04167 2.70834
You should notice two things, first that as we add more terms we are getting closer to the exact value of e(1), also that the difference between consecutive sums are getting smaller.
So, an implementation of e(x) could be written as:
#include <stdbool.h>
#include <stdio.h>
#include <math.h>
typedef float (*term)(int, int);
float evalSum(int, int, int, term);
float expTerm(int, int);
int fact(int);
int mypow(int, int);
bool sgn(float);
const int maxTerm = 10; // number of terms to evaluate in series
const float epsilon = 0.001; // the accepted error
int main(void)
{
// change these values to modify the range and increment
float start = -2;
float end = 2;
float inc = 1;
for(int x = start; x <= end; x += inc)
{
float value = 0;
float prev = 0;
for(int ndx = 0; ndx < maxTerm; ndx++)
{
value = evalSum(0, ndx, x, expTerm);
float diff = fabs(value-prev);
if((sgn(value) && sgn(prev)) && (diff < epsilon))
break;
else
prev = value;
}
printf("the approximate value of exp(%d) is %f\n", x, value);
}
return 0;
}
I've used as a guess that we will not need to use more then ten terms in the expansion to get to the desired precision, thus the inner for loop is where we loop over values of n in the range [0,10].
Also, we have several lines dedicated to checking if we reach the required precision. First I calculate the absolute value of the difference between the current evaluation and the previous evaluation, and take the absolute difference. Checking if the difference is less than our epsilon value (1E-3) is on of the criteria to exit the loop early. I also needed to check that the sign of of the current and the previous values were the same due to some fluctuation in calculating the value of e(-1), that is what the first clause in the conditional is doing.
float evalSum(int start, int end, int val, term fnct)
{
float sum = 0;
for(int n = start; n <= end; n++)
{
sum += fnct(n, val);
}
return sum;
}
This is a utility function that I wrote to evaluate the first n-terms of a series. start is the starting value (which is this code always 0), and end is the ending value. The final parameter is a pointer to a function that represents how to calculate a given term. In this code, fnct can be a pointer to any function that takes to integer parameters and returns a float.
float expTerm(int n, int x)
{
return (float)mypow(x,n)/(float)fact(n);
}
Buried down in this one-line function is where most of the work happens. This function represents the closed form of a Taylor expansion for e(n). Looking carefully at the above, you should be able to see that we are calculating $\fract{x^n}{n!}$ for a given value of x and n. As a hint, for doing the cosine part you would need to create a function to evaluate the closed for a term in the Taylor expansion of cos. This is given by $(-1)^n\fact{x^{2n}}{(2n)!}$.
int fact(int n)
{
if(0 == n)
return 1; // by defination
else if(1 == n)
return 1;
else
return n*fact(n-1);
}
This is just a standard implementation of the factorial function. Nothing special to see here.
int mypow(int base, int exp)
{
int result = 1;
while(exp)
{
if(exp&1) // b&1 quick check for odd power
{
result *= base;
}
exp >>=1; // exp >>= 1 quick division by 2
base *= base;
}
return result;
}
A custom function for doing exponentiation. We certainly could have used the version from <math.h>, but because I knew we would only be doing integer powers we could write an optimized version. Hint: in doing cosine you probably will need to use the version from <math.h> to work with floating point bases.
bool sgn(float x)
{
if(x < 0) return false;
else return true;
}
An incredibly simple function to determine the sign of a floating point value, returning true is positive and false otherwise.
This code was compiled on my Ubuntu-14.04 using gcc version 4.8.4:
******#crossbow:~/personal/projects$ gcc -std=c99 -pedantic -Wall series.c -o series
******#crossbow:~/personal/projects$ ./series
the approximate value of exp(-2) is 0.135097
the approximate value of exp(-1) is 0.367857
the approximate value of exp(0) is 1.000000
the approximate value of exp(1) is 2.718254
the approximate value of exp(2) is 7.388713
The expected values, as given by using bc are:
******#crossbow:~$ bc -l
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
e(-2)
.13533528323661269189
e(-1)
.36787944117144232159
e(0)
1.00000000000000000000
e(1)
2.71828182845904523536
e(2)
7.38905609893065022723
As you can see, the values are well within the tolerances that you requests. I leave it as an exercise to do the cosine part.
Hope this helps,
-T
exp and cos have power series that converge everywhere on the real line. For any bounded interval, e.g. [-pi/4, pi/4] or [-2, 2], the power series converge not just pointwise, but uniformly to exp and cos.
Pointwise convergence means that for any x in the region, and any epsilon > 0, you can pick a large enough N so that the approximation you get from the first N terms of the taylor series is within epsilon of the true value. However, with pointwise convergence, the N may be small for some x's and large for others, and since there are infinitely many x's there may be no finite N that accommodates them all. For some functions that really is what happens sometimes.
Uniform convergence means that for any epsilon > 0, you can pick a large enough N so that the approximation is within epsilon for EVERY x in the region. That's the kind of approximation that you are looking for, and you are guaranteed that that's the kind of convergence that you have.
In principle you could look at one of the proofs that exp, cos are uniformly convergent on any finite domain, sit down and say "what if we take epsilon = .001, and the regions to be ...", and compute some finite bound on N using a pen and paper. However most of these proofs will use at some steps some estimates that aren't sharp, so the value of N that you compute will be larger than necessary -- maybe a lot larger. It would be simpler to just implement it for N being a variable, then check the values using a for-loop like you did in your code, and see how large you have to make it so that the error is less than .001 everywhere.
So, I can't tell what the right value of N you need to pick is, but the math guarantees that if you keep trying larger values eventually you will find one that works.

Calculating smallest number of coins error

I've recently started an online course in C, and am working through the second question in PS1. The question requires us to request an input of change from a user in dollars, and to calculate the smallest number of coins you can give them that change with, provided you are only allowed 25 cent, 10 cent, 5 cent and 1 cent coins.
For example 50 cents would be 2 25 cent coins, and 65 cents would be 2 25 cent coins, 1 10 cent coin and 1 5 cent coin.
Here is my code:
#include <stdio.h>
#include <cs50.h>
int main(void)
{
float change = 0;
int coinCounter = 0;
int remainder = 0;
int remainder1 = 0;
int remainder2 = 0;
int remainder3 = 0;
.
do
{
printf("Please enter the change in dollars: ");
change = GetFloat();
}
while(change <= 0);
//converts amount in dollars to cents
change = change*100;
//We want to use the largest number of big cois as possible to make up the change.
// This calculates the remainder (if any) after dividing the change by 25. % = modulo, only works with integer operands.
remainder = (int)change % 25;
//(change - remainder) gets us the largest number divisible by 25. This line then calculates
// the maximum number of 25cent coins we can use, and sets this number equal to the coinCounter.
coinCounter = ((int)change - remainder)/25;
//Finds the remainder (if any) when dividing the last remainder by 10.
remainder1 = remainder % 10;
//(remainder - remainder1) gets us the largest number divisible by 10. Dividing this by 10, we
// determine the max amount of 10 cent coins we can use to make up the required change. We then add
// this number of coins to the total coinCounter.
coinCounter = coinCounter + ((remainder - remainder1)/10);
//Again, take the remainder (if any) from the last calculation, and find the remainder when dividing by 5.
remainder2 = remainder1 % 5;
// (remainder1 - remainder2)/5 tells us the number of 5 cent coins we need to make up the required change.
// We add the number of coins to the coin counter.
coinCounter = coinCounter + ((remainder1 - remainder2)/5);
//Finds the remainder when dividing last remainder by 1. There will actually be no remainder, so remainder 3 will
// equal zero.
remainder3 = remainder2 % 1;
//Here, (remainder2 - remainder1)/1 Finds the number of 1 cent coins required to make up the left change.
// remainder3 will always be zero. Hence (remainder2)/1 will always be equal to remainder 2. We add this number
// of 1 cent coins to the coinCounter.
coinCounter = coinCounter + ((remainder2 - remainder3)/1);
//We print out coinCounter, which is the smallest number of coins required to make up the change.
printf("%i\n",coinCounter);
}
Now I am new to programming, so I am very aware that there are probably far more efficient ways of tackling this problem. However, this seems to work fairly well. However, strangely, I get an incorrect result when I try '4.2'. I should get 18 coins (16 25 cent coins and 2 10 cent coins), however the program displays 22. It works well for all other numbers I have tried however.
I cannot figure out what I have done wrong. I feel like it either has something to do with where I change dollars to cents by multiplying by 100, OR, where I calculate the modulo and cast change to an int, but I unfortunately cannot figure it out alone.
I have heavily annotated my code so it is somewhat easier to understand. I hope someone can help me with this!
I would do something simpler, like:
int main(void)
{
float change = 0;
int coinCounter = 0;
int remainder = 0;
int remainder1 = 0;
int remainder2 = 0;
do
{
printf("Please enter the change in dollars: ");
change = GetFloat();
}
while(change <= 0);
change = change*100;
coinCounter = (int)change/25; //number of 25cents
remainder = change % 25; //rest
if(remainder > 0){
coinCounter += (int)remainder/10; //number of 10cts
remainder1 = remainder%10;
}
if(remainder1 > 0){
coinCounter += (int)remainder1/5; //number of 5cts
remainder2 = remainder1%5
}
coinCounter += remainder2; //number of 1cts
printf("%i\n",coinCounter);
}
Does it solve your problem with 4.2 ? I can't test right now.
The issue is that you have taken the change variable as a float, while all the other variables are ints.
The conversion of a float to an int introduces small unpredictable errors and can fail in some cases.
If you are interested in there is a very good article here.
I would suggest that you take the input as cents, or if that is not possible, take another integer variable and convert to cents at the start of the program and use that instead in the calculations.
As EOF has (rather snarkily) pointed out in their comment you are running into an issue with floating point numbers. Floating point numbers are a not perfect, there are many (infinitely many) numbers that can't be exacltly represented by a C float or double.
There's lots of good information on the web about this, for example here but the short explanation is that some decimal values when calculated in C using floats give the wrong answer and one such number is 4.2 * 100 in your particular compiler.
One possible solution in your case is to convert the float to a long, so something like:
change = change * 100 ;
long value = change >= 0 ? (long)(change+0.5) : (long)(change-0.5) ;
This should give you the exact number of cents and remove the small error in the floating calculation.
As an aside these effects can be dificult to see sometimes, try printing the result of this:
float x = 4.2 * 100 ;
float y = 4.2 ;
y = y * 100 ;
In my compiler this does result in 420 in x but 419.99... in y.
As others have pointed out, floating point values cannot always be represented perfectly. To address the error, you can round to the nearest integer. Here is a very simple function to start with:
int round(float number)
{
return (number >= 0) ? (int)(number + 0.5) : (int)(number - 0.5);
}
Use it in your code like this:
int main(void)
{
float change = 0;
int changed = 0;
int coinCounter = 0;
int remainder = 0;
int remainder1 = 0;
int remainder2 = 0;
int remainder3 = 0;
do
{
printf("Please enter the change in dollars: ");
change = GetFloat();
}
while(change <= 0);
//converts amount in dollars to cents
changed = round(change*100);//changes 419... to 420 etc.
...(more code)
You will have to experiment with corner cases to make it work well for all conditions, but this will get you started.
Note: this code example for rounding is over simplified, and provided just to get you started. The problem is really more complicated as illustrated by this conversation dealing with rounding floats to nearest integer value.

Not getting correct output when trying to print a double in C

This should be a simple fix. So I am trying to get segments of a length to print out to use as a variable in the future. The problem is that the variable will not initialize correctly. (Ignore the commented sections for that is for once I get this problem fixed)
The problem lies with this line: double h = (1/m);
int main(void) {
int t = 1; //time
int m = 0; //number of segments of bar
int n = 0; //number of intervals related to time
printf("Enter number of segments: ");
scanf("%d", &m);
printf("Enter number of time intervals: ");
scanf("%d", &n);
printf("%d", m);
printf("\n");
double h = (1/m); //length of bar segments
double d = (1/n); //length of time interval
printf("%lf", h);
printf("\n");
printf("%d", m);
printf("\n");
}
My output:
Enter number of segments: 5
Enter number of time intervals: 10
5
0.000000
5
Program ended with exit code: 0
The correct output shouldn't be 0.00000, it should be 0.20000. I realize this is probably something I am missing but still I cannot seem to figure it out.
Integer calculations are truncated to integer values, even when you subsequently assign them to a double. Think of the following:
double h = 1 / m;
as:
do the integer calculation 1 / m which, truncated, gives zero for the vast majority of m values.
convert that zero to a double (it's still a zero) and assign it to h.
This is specified in the ISO standard, C11 6.5.5 Multiplicative operators /6 (my italics):
When integers are divided, the result of the / operator is the algebraic quotient with any
fractional part discarded.
What you need is:
double h = 1.0 / m;
double d = 1.0 / n;
to ensure the calculation itself is performed as a floating point one.
double h = (1/m); //length of bar segments
double d = (1/n); //length of time interval
These operations do integer division. Try
double h = (1.0/m); //length of bar segments
double d = (1.0/n); //length of time interval

Resources