How to add two fractions? - c

Assuming that these functions are already given:
include <stdio.h> /* printf */
include "fractions.h" /* struct FRACTION, add_fractions */
struct FRACTION make_fraction(int numerator, int denominator)
{
struct FRACTION f;
f.numerator = numerator;
f.denominator = denominator;
return f;
}
void test_fraction(int numerator1, int denominator1,
int numerator2, int denominator2)
{
struct FRACTION a = make_fraction(numerator1, denominator1);
struct FRACTION b = make_fraction(numerator2, denominator2);
struct FRACTION c = add_fractions(&a, &b);
printf("%i/%i + %i/%i = %i/%i\n", a.numerator, a.denominator,
b.numerator, b.denominator,
c.numerator, c.denominator);
}
void testGCD(void)
{
int m, n;
m = 15; n = 18; /* GCD is 3 */
printf("GCD of %i and %i is %i\n", m, n, GCD(m, n));
printf("GCD of %i and %i is %i\n", n, m, GCD(n, m));
m = 80; n = 20; /* GCD is 20 */
printf("GCD of %i and %i is %i\n", m, n, GCD(m, n));
printf("GCD of %i and %i is %i\n", n, m, GCD(n, m));
m = 21; n = 47; /* GCD is 1 */
printf("GCD of %i and %i is %i\n", m, n, GCD(m, n));
printf("GCD of %i and %i is %i\n", n, m, GCD(n, m));
m = 68; n = 153; /* GCD is 17 */
printf("GCD of %i and %i is %i\n", m, n, GCD(m, n));
printf("GCD of %i and %i is %i\n", n, m, GCD(n, m));
}
int main(void)
{
testGCD();
test_fraction(2, 3, 1, 6);
test_fraction(1, 5, 4, 9);
test_fraction(3, 7, 12, 21);
test_fraction(5, 8, 3, 16);
test_fraction(7, 8, 3, 12);
test_fraction(0, 8, 3, 16);
test_fraction(1, 1, 3, 16);
test_fraction(5, 8, -3, 16);
test_fraction(1, 5, -4, 9);
test_fraction(-1, 5, -4, 9);
return 0;
}
My task is to write GCD() and add_fractions(), and this is what I have written:
include "fractions.h"
struct FRACTION add_fractions(const struct FRACTION *a, const struct FRACTION *b)
{
struct FRACTION c ; /*result struct*/
/* int GCD_a = GCD(a.numerator, a.denominator); GCD of the fraction a*/
/*int GCD_b = GCD(b.numerator, b.denominator); GCD of the fraction b*/
c.numerator = (a.numerator) + (b.numerator);
c.denominator = a.denominator ;
return c;
/* struct FRACTION empty;*/
/*return empty;*/
}
int GCD(int a, int b)
{
/*Variables*/
int remainder = 0; /*remainder*/
int larger = a;
int smaller = b;
remainder = larger % smaller;
while (remainder != 0)
{
larger = smaller;
smaller = remainder;
remainder = larger % smaller;
}
return smaller;
}
Assuming that for the moment both denominators are equals, why I can't run this with Cygwin? I use this command to compile
gcc -Wall -Wextra -ansi -pedantic -Wno-unused-parameters main.c fractions.c -o fractions.exe
and I have two errors: (Cygwin is in Spanish on my computer so I am not sure that what I am going to write is the exact translation):
error: trying to put "numerator" in something which is not a struct
(and the same for denominator)
What is the problem?

const struct FRACTION *a, const struct FRACTION *b
So a and b are pointers to a constant struct FRACTION. Then later you write:
c.numerator = (a.numerator) + (b.numerator);
you don't access members of struct pointers using ., but using ->, this should be
c.numerator = a->numerator + b->numerator;
P. s. 1: the parentheses are not needed, don't put them in superfluously, they decrease readability.
P. s. 2: your addition formula is broken, use
c.numerator = a->numerator * b->denominator + b->numerator * a->denominator;
c.denominator = a->denominator * b->denominator;
instead.

In your add_fractions function, you've declared a and b as pointers to struct FRACTION:
struct FRACTION add_fractions(const struct FRACTION *a, const struct FRACTION *b)
Since a and b are pointers, not structs, you can't write things like a.numerator.
You either need to dereference a and b before using the . operator:
c.numerator = ((*a).numerator) + ((*b).numerator);
c.denominator = (*a).denominator ;
or use the -> component selection operator, which is a shorthand way of doing the same thing:
c.numerator = (a->numerator) + (b->numerator);
c.denominator = a->denominator ;

In addition to user529758's point that your addition algorithm should be
n1 * d2 + n2 * d1
= ------------------
d1 * d2
I believe Jonathan's point needs to be emphasized that you will then need to divide the numerator and denominator of the result through by the GCD to reduce the resulting fraction to its lowest form.
For example, you can implement a new function to do the reduction:
struct FRACTION reduce_fraction(const struct FRACTION *frac)
{
struct FRACTION reduced;
int gcd = GCD(frac->numerator, frac->denominator);
reduced.numerator = frac->numerator / gcd;
reduced.denominator = frac->denominator / gcd;
return reduced;
}
Your add_fraction function will now look like this:
struct FRACTION add_fractions(const struct FRACTION *a, const struct FRACTION *b)
{
struct FRACTION c;
c.numerator = (a->numerator * b->denominator) + (b->numerator * a->denominator);
c.denominator = a->denominator * b->denominator;
return reduce_fraction(&c);
}
Also, given that you've done the hard work in determining what the result should be in the comments, instead of printfing to stdout, why not assert these - this provides the basis for automated unit tests:
#include <assert.h>
...
m = 15; n = 18;
assert(GCD(m, n) == 3);
assert(GCD(m, n) == GCD(n,m));
m = 80; n = 20;
assert(GCD(m, n) == 20);
assert(GCD(m, n) == GCD(n,m));
And the same for add_fractions and reduce_fraction, as well :)

Related

Run time errors while computing e^x

Continuing from the question I posted before How to increase precision for function e^x
I made few changes in my code by taking advices given
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
long double exponential(long double x, long double n, long double p)
{
long double i = 1;
while (n > 0) // loop stops when becomes less than 0
i = i + (x / p) * (exponential(x, n - 0.0001, p + 1));
if (n < 0) // when n reaches 0 or becomes less than zero value of i will be returned
return i;
}
int main()
{
long double p, x, n;
scanf("%Lf", &x);
printf("math.h e^x = %lf\n", exp(x));
printf("calculated e^x = %Lf\n", exponential(x, 1, 1));
return 0;
}
But I am not getting any output its just giving run time error(http://codepad.org/jIKoYGFC) and I don't know why . Please can some one help me why I am getting these errors
That loop is completely bogus. You're not writing an iterative function (where it would make more sense). Further you have an edge case of zero returning undefined content.
Though I do not recommend floating point for loop control, nor do I advise thousands of invocations into recursive calls, your code should be more like
long double exponential(long double x, long double n, long double p)
{
long double i = 1;
if (n > 0)
i += (x / p) * (exponential(x, n - 0.0001, p + 1));
return i;
}
which ultimately is just this:
long double exponential(long double x, long double n, long double p)
{
return 1 + ((n > 0) ? (x / p) * exponential(x, n - 0.0001, p + 1) : 0);
}
Fixing that (either way):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
long double exponential(long double x, long double n, long double p)
{
return 1 + ((n > 0) ? (x / p) * exponential(x, n - 0.0001, p + 1) : 0);
}
int main()
{
long double x = 5;
printf("math.h e^x = %Lf\n", expl(x));
printf("calculated e^x = %Lf\n", exponential(x, 1, 1));
return 0;
}
Output
math.h e^x = 148.413159
calculated e^x = 148.413159
Created a version using LibGMP out of curiosity to see how this will improve the outcome.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gmp.h>
#define BITS 128
The line above mean mantissa is 128 bits and exponent of 64 bits. This is my GMP based function:
void gmp_exponential(mpf_t * i, double x, double n, int p)
{
mpf_t ii;
mpf_init(ii);
mpf_set_d(ii,1);
if (n > 0){
mpf_t a,b,c;
gmp_exponential(&ii, x, n - 0.0001, p + 1);
mpf_inits (a, b, c, NULL);
mpf_set_d(a,x);
mpf_div_ui(b, a, p) ;
mpf_mul(c, b, ii);
mpf_add (*i,*i,c);
mpf_clears(a,b,c,NULL);
}
mpf_clear(ii);
}
Reusing the function from WhozCraig for comparison:
long double exponential(long double x, long double n, long double p)
{
return 1 + ((n > 0) ? (x / p) * exponential(x, n - 0.0001, p + 1) : 0);
}
And code to run it all:
int main()
{
double x = 30.0;
mpf_t i;
mpf_init2 (i, BITS);
mpf_set_d(i,1);
gmp_exponential(&i, x, 1, 1);
printf ("math.h e^x = %Lf\n", expl(x));
gmp_printf ("calculated e^x with mpf = %.*Ff\n", 6, i);
printf ("calculated e^x = %Lf\n", exponential(x, 1, 1));
mpf_clear(i);
return 0;
}
Output:
math.h e^x = 10686474581524.462147
calculated e^x with mpf = 10686474581524.462143
calculated e^x = 10686474581524.462149

Write a program to take 2 numbers to divide it, take sum of the decimals from division value to output

This program will take 3 interger values a, b and N.
The program will find the sum of the decimals from division value of (a/b) up to N numbers.
For example:
Sorry my technical english wasn't very good, my program (in C) should do the following:
It takes values of a, b, and N
It perform division of a and b
It takes the division in float and separate it into integer value and fractional part
It add to sum of fractional part rounded down
It update the base division value by multiply by 10
It update conditions of the loop of n=N
Output in printf.
However, my program only give the right value up till a=252525 b=99 N=33 output=171 which i think is wrong. Please help me correct my algorithm.
#include<stdio.h>
int main()
{
unsigned int a, b, N;
int n;
double x,inte, frac; //x is output, integer part, fractional part
long double div; //division value of a/b
printf("Enter so nguyen duong a : \n"); scanf("%d",&a);
printf("Enter so nguyen duong b : \n"); scanf("%d",&b);
printf("Enter so nguyen duong N : \n"); scanf("%d",&N);
div = (long double) a / (long double)b;
x = 0;
for(n=0;n<N;n++)
{
frac = modf(div,&inte); //perform separating integer and fractional part of division
x = x + (int)floor(frac*10); //round down the fractional part of division
div=frac*10;
}
printf("a / b = %.20f\n",(double) a / (double)b);
printf ("tong cua %i chu so sau dau phay la = %.0f\n",N,x);
}
It would be simpler (and accurate, as #user3386109 pointed out, floating point arithmetic will begin to loose precision as the number of decimals increase) if you devise your own "integer division function"; something like below (the function divide).
edit:
Tested for a = 252525, b = 99, N = 33; output was 199 which seem OK to me. The fraction part is like ".7575757575..."; the first 32 digits add up to 16 * 12 = 192, adding the last "7" (33rd digit) makes 199.
void divide(
unsigned int a,
unsigned int b,
unsigned int *d,
unsigned int *r
) {
*d = a / b;
*r = a - *d * b;
return;
}
unsigned int sum(
unsigned int a,
unsigned int b,
unsigned int n
) {
unsigned int k = 0;
unsigned int d = 0; // division
unsigned int r = 0; // remainder
unsigned int s = 0; // sum
// do an intial integer division to reach the decimal part
divide(a, b, &d, &r);
while (k < n) {
a = r * 10;
divide(a, b, &d, &r);
s += d;
k++;
}
return s;
}
int main() {
unsigned int a = 20;
unsigned int b = 13;
unsigned int n = 4;
printf("first %u decimal sum of division %u / %u = %u\n", n, a, b, sum(a, b, n));
a = 25;
b = 3;
n = 5;
printf("first %u decimal sum of division %u / %u = %u\n", n, a, b, sum(a, b, n));
a = 4;
b = 2;
n = 10;
printf("first %u decimal sum of division %u / %u = %u\n", n, a, b, sum(a, b, n));
a = 2020;
b = 21;
n = 6;
printf("first %u decimal sum of division %u / %u = %u\n", n, a, b, sum(a, b, n));
return 0;
}

Fast formula to get the range a number is in, given a perfect binary subdivision?

Mind the set of positive integers from 0 til L exclusive. For any positive integer n up to log2(K), can split the set in 2^n consecutive subsets of equal length. For example, for L = 256, n = 3, we'd get 2^3, or 8, subsets: {0..31}, {32..63}, {64..95}, {96..127}, {128..160}, {160..191}, {192..223}, {224..255}.
Let f(L,n,i) : Nat -> Nat -> Nat -> (Nat,Nat) return, given an arbitrary L and n, the subset that some i is contained in. For example, for f(256,3,100) = (96,127), because, if we divide the 0..255 range in 2^3 subsets, then number 100 is contained in the subset ranging from 96 to 127.
My question is, what is a fast implementation of f? I wonder if it is possible to do so in constant time, with just a few bitwise operations.
This works:
#include <stdio.h>
typedef struct { int a, b; } pair;
pair f(int L, int n, int i) {
int len = L / (1 << n);
int a = i / len * len;
return (pair) { a, a + len - 1 };
}
int main() {
pair p = f(256, 3, 100);
printf("%d %d\n", p.a, p.b);
}
I am not good with floating point, but looping works as expected:
#include <stdio.h>
#include <math.h>
typedef struct { double a, b; } paird;
paird fd(double L, double n, double i) {
double len = L / pow(2, n);
double a = 0, b;
while (b = a + len, b < i) {
a = b;
}
return (paird){ a, b };
}
int main() {
paird p = fd(127, 7, 100);
printf("%f %f\n", p.a, p.b); // (99.218750, 100.210938)
}
Quite obviously, just compute the length of each subset (l), divide i by l, and take the floor k. The desired range goes from l*k to l*(k+1)-1. In JavaScript:
function subrange_of_i(L, n, i) {
var l = L / (2 ** n); // or just `L >>> n`
var k = Math.floor(i / l);
return [l*k, l*(k+1)-1];
};
(TODO: convert to C for the sake of this answer.)

Reverse the output of printf function in while loop

I wrote a code for a b-adic representation of a chosen number.
#include <stdio.h>
int b_adisch (int a, int b)
{
int x, y, mod, mod1;
x = a / b;
mod1 = a % b;
printf("%i\n", mod1);
do {
y = x / b;
mod = x % b;
x = y;
printf("%i\n", mod);
} while(x != 0);
return a ;
}
int main (void)
{
int a, b;
printf("pls input a ");
scanf("%i", &a);
printf("pls input b ");
scanf("%i", &b);
b_adisch(a, b);
return 0;
}
The output order will be reversed
since the printf has to be put into the while loop and the calculation starts with the last number of the representation.
Example if a = 10 and b = 2
The output is 0101
but it should be 1010
How can I change my code to make this happen?
How can i change my code to make this happen?
2 approaches:
Compute the digits from least to most significant and save in a adequate sized buffer. This is similar to OP's approach yet saves the results of each digit's computation for later printing.
#include <assert.h>
#include <limits.h>
void b_adisch(int value, int base) {
// Let us work with simple cases first.
assert(value >= 0);
assert(base >= 2 && base <= 10);
// Adequate sized buffer
char buffer[sizeof value * CHAR_BIT + 1];
// Start at end
char *end = &buffer[sizeof buffer - 1];
*end = '\0';
do {
end--;
int digit = value%base; // Find least digit
value /= base;
*end = digit + '0'; // save the digit as text
} while (value);
printf("<%s>\n", end); // print it as a string
}
Use recursion. A more radical change; This computes and prints the output of the more significant digits first.
void b_adischR_helper(int value, int base) {
// If the value is at least 2 digits, print the most significant digits first
if (value >= base) {
b_adischR_helper(value/base, base);
}
putchar(value % base + '0'); // Print 1 digit as text
}
void b_adischR(int value, int base) {
// Let us work with simple cases first.
assert(value >= 0);
assert(base >= 2 && base <= 10);
printf("<");
b_adischR_helper(value, base);
printf(">\n");
}
Test
int main() {
b_adisch(10, 2);
b_adischR(10, 2);
b_adisch(INT_MAX, 10);
b_adischR(INT_MAX, 10);
b_adisch(INT_MAX, 2);
b_adischR(INT_MAX, 2);
}
Output
<1010>
<1010>
<2147483647>
<2147483647>
<1111111111111111111111111111111>
<1111111111111111111111111111111>
You can store the output in an array as here it is stored in "arr" and later print the output in reverse order (from end to start).
#include <stdio.h>
int arr[10000]={0};
void b_adisch (int a, int b)
{
int x, y, mod, mod1,i=0,j;
x = a / b;
mod1 = a % b;
arr[i++]=mod1;
do {
y = x / b;
mod = x % b;
x = y;
arr[i++]=mod;
} while(x != 0);
for(j=i-1;j>=0;j--)
printf("%i\n",arr[j]);
}
int main (void)
{
int a, b;
printf("pls input a ");
scanf("%i", &a);
printf("pls input b ");
scanf("%i", &b);
b_adisch(a, b);
return 0;
}

Swap digits in a double in C [duplicate]

This question already has answers here:
Exchange 1000s digit with 10s digit (C)
(3 answers)
Closed 5 years ago.
What I want to do in C is swap two digits in a double.
For example, if the input is 54321.987 and I want to swap the 2nd with the 4th digit, the output should be 52341.987.
Example when too small: 12.34 would output 1002.34.
Using stringification approach:
There are more elegant ways, but you can see the steps (and improve on) this pseudo code to stringify, move values, and convert back to number.
char buf1[20];
char buf2[20];
char *dummy;
double val = 54321.987;
sprintf(buf1, "%9.3f", val );
//Now the number is in string form: "54321.987". Just move the two elements
buf2[0]=buf1[0];
buf2[1]=buf1[3];
buf2[2]=buf1[2];
buf2[3]=buf1[1]; //and so on
//now convert back:
val = strtod(buf2, &dummy);
printf("%9.3f\n", val);
Or, a function could be used to do essentially the same thing: (still stringification)
double swap_num_char(double num, int precision, int c1, int c2); //zero index for c1 and c2
int main(void)
{
double val = 54321.987;
printf("%9.3f\n", swap_num_char(val, 3, 1, 3));
return 0;
}
double swap_num_char(double num, int precision, int c1, int c2)
{
char buf[25];
char format[10];
char *dummy;
char c;
sprintf(format, "%s0.%df", "%", precision);
sprintf(buf, format, num);
c = buf[c1];
buf[c1] = buf[c2];
buf[c2] = c;
num = strtod(buf, &dummy);
return num;
}
You can get the two digits you're interested in with simple operations:
You can do so with
double x = 54321.987;
double tens = ((int)(x / 10)) % 10; // Result is 2
double thousands = ((int)(x / 1000)) % 10; // Result is 4
Then you can subtract out the digits from their original place,
and add them back in a new place:
x = x - (tens * 10.0) - (thousands * 1000.0); // result is 50301.987
x = x + (tens * 1000.0) + (thousands * 10.0); // result is 52341.987
Now just reduce the expression:
x = x + tens * (1000.0 - 10.0) - thousands * (1000.0 - 10.0);
This leaves you with a final expression:
x += (tens - thousands) * 990.0;
Or, if you don't want the intermediate variables:
x += (((int)(x/10))%10 - ((int)(x/1000))%10) * 990;
One solution would be to extract the digits, then swap them.
You extract the digits (from positive numbers, at least) by using floor():
int place1 = 1; /* 0-based*/
double desiredPowerOf10 = powersOf10[place1];
double nextPowerOf10 = powersOf10[place1 + 1];
double digit1 = floor(number / desiredPowerOf10) - floor(number/nextPowerOf10) * 10;
You can then subtract the digits and add them back with the different powers:
double digitsRemoved = number - (digit1 * power1 + digit2 * power2);
double digitsSwapped = digitsRemoved + digit1 * power2 + digit2 * power1;
This may be susceptible to loss of precision with very large numbers, though.
1 - Use modf() to break the number into whole and fractional parts.
double modf(double value, double *iptr);
The modf functions break the argument value into integral and fractional parts, C11 ยง7.12.6.12
2 - Print the whole number part as a string and do the swap.
3 - Reconstruct
#include <float.h>
#include <math.h>
#include <stdio.h>
double swap2_4digit(double x) {
if (signbit(x)) {
return -swap2_4digit(-x);
}
printf("Before %f\n", x);
double ipart;
double fpart = modf(x, &ipart);
// ms_digit digits '.' '\0' min_size
char buf[1 + DBL_MAX_10_EXP + 1 + 1 + 4]; // Insure buffer is big enough
strcpy(buf, "0000"); // Handle small numbers
sprintf(buf + strlen(buf), "%.0f", ipart);
size_t len = strlen(buf);
char ch = buf[len - 2];
buf[len - 2] = buf[len - 4];
buf[len - 4] = ch;
x = atof(buf) + fpart;
printf("After %f\n", x);
return x;
}
int main(void) {
swap2_4digit(54321.987);
swap2_4digit(12.34);
}
Output
Before 54321.987000
After 52341.987000
Before 12.340000
After 1002.340000
Something left for OP. Make general for other digit positions.
If you want input number to be double then you can do something like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
double numbergiven = 56789.1234;
double dummy;
double _4th_digit = (10*modf(numbergiven/10000, &dummy)) - modf(numbergiven/1000, &dummy);
double _2th_digit = (10*modf(numbergiven/100, &dummy)) - modf(numbergiven/10, &dummy);
numbergiven = numbergiven - (_4th_digit * 1000) + (_2th_digit * 1000);
numbergiven = numbergiven + (_4th_digit * 10) - (_2th_digit * 10);
printf("%lf",numbergiven);
return 0;
}
If you are not familiar with modf then you can simply do it this way:
#include <stdio.h>
#include <stdlib.h>
int main()
{
double numbergiven = 56789.1234;
int number = numbergiven;
int _4th_digit = (number/1000) - (10*(number/10000));
int _2th_digit = (number/10) - (10*(number/100));
numbergiven = numbergiven - (_4th_digit * 1000) + (_2th_digit * 1000);
numbergiven = numbergiven + (_4th_digit * 10) - (_2th_digit * 10);
printf("%lf",numbergiven);
return 0;
}
or use fmod() #John Bollinger.
The fmod functions compute the floating-point remainder of x/y.
Extract the 2 digits each with the difference of modding with 10place and modding with 10place-1.
Subtract the 2 digits and then add them back swapped.
double swap_digit(double x, unsigned a, unsigned b) {
printf("Before %f\n", x);
double a_place = pow(10.0, a);
double b_place = pow(10.0, b);
double scaled_digit_a = fmod(x, a_place) - fmod(x, a_place/10);
double scaled_digit_b = fmod(x, b_place) - fmod(x, b_place/10);
x -= scaled_digit_a + scaled_digit_b;
x += scaled_digit_a/a_place*b_place + scaled_digit_b/b_place*a_place;
printf("After %f\n", x);
return x;
}
int main(void) {
swap_digit(54321.987,2,4);
swap_digit(12.34,2,4);
}
Output
Before 54321.987000
After 52341.987000
Before 12.340000
After 1002.340000
Double is stored in a memory as a sequence of bits, but you want to operate with decimal digits. Doing this with double variable you may not receive the original digits because of floating-point arithmetic.
Therefore, you should manipulate with string representation of double. The main aspect is how many digits string will contain. But it's obvious that you get number from input. Scan it as string, not as double.
There is a working code:
#include <stdio.h>
#include <stddef.h>
#define BUFSIZE 255
void swap_digits(char *str, int n, int m) {
char *digit1 = NULL;
char *digit2 = NULL;
int count = 0;
while (*str && (!digit1 || !digit2)) {
if (*str != '.') {
count++;
if (count == n) {
digit1 = str;
}
if (count == m) {
digit2 = str;
}
}
str++;
}
if (digit1 && digit2) {
char tmp = *digit1;
*digit1 = *digit2;
*digit2 = tmp;
}
}
int main(void) {
char buffer[BUFSIZE];
scanf("%s", buffer);
// it is preferably to validate input
swap_digits(buffer, 2, 4);
printf(buffer);
return 0;
}

Resources