Lowest Common Multiple with doubles in C - c

I am doing an assignment for a Coursera class that asks me to calculate the Lowest Common Multiple of two numbers, either of which are no larger than 2 * 10 ^ 9. I'm writing this in C and I'm running my code on a test case with the numbers 226553150 and 1023473145. The answer is 46374212988031350, but I'm getting 46374212988031344, which is off by 6!
I've written a correct solution in Python that uses essentially the same approach as the one I've posted below, but the details of numeric precision are obviously taken care of for me. I post this to SO to learn something about floating point precision in C, and because most of the questions I've seen on the internet and SO regarding LCM deal only with integers.
Here is my code, which I'm compiling with gcc -pipe -O2 -std=c11 lcm.c:
#include <stdio.h>
#include <math.h>
double gcd(double a, double b) {
if (b == 0) {
return a;
}
return gcd(b, fmod(a,b));
}
double lcm(double a, double b) {
return (a * b) / gcd(a,b);
}
int main() {
double a;
double b;
scanf("%lf %lf", &a, &b);
printf("%.0lf\n", lcm(a,b));
return 0;
}

The closest number to 46374212988031350 that can be represented by a double is 46374212988031352 (off by 2). You can test that by using the most straight forward calculation.
#include <stdio.h>
int main() {
// The gcd of 226553150 and 1023473145 is 5
double a = 226553150;
double b = 1023473145;
double c = b/5;
double lcm = a*c;
printf("lcm: %.0lf\n", lcm);
return 0;
}
Output:
lcm: 46374212988031352
You are making things worse by computing (a * b)/gcd(a, b). The closest number to 231871064940156750, (a*b), that can be represented by floating point numbers is 231871064940156736. In other words, you are losing more accuracy by computing (a*b) first.
You haven't posted the Python code you used to do the same computation. I am guessing Python is using integral types for the numbers. If I use:
a = 226553150;
b = 1023473145;
c = b/5;
lcm = a*c
print("lcm:", lcm)
I get the output:
('lcm:', 46374212988031350)
However, if I use floating point literals for a and b, I get a different output:
a = 226553150.0;
b = 1023473145.0;
c = b/5;
lcm = a*c
print("lcm:", "%18.0lf" % lcm)
Output:
('lcm:', ' 46374212988031352')
In summary, the difference you are seeing between the C program and the Python program is due to use of floating point types vs integral types. If you use long or long long instead of double, you should get the same output as the Python program, as shown in the answer by Deng Haijun.

I doubt why you use float not long. I change float to long as following, then it works fine.
#include <stdio.h>
#include <math.h>
long gcd(long a, long b) {
if (b == 0) {
return a;
}
return gcd(b, a%b);
}
long lcm(long a, long b) {
return (a * b) / gcd(a,b);
}
int main() {
long a;
long b;
scanf("%ld %ld", &a, &b);
printf("%ld\n", lcm(a,b));
return 0;
}

Related

C - Subtraction of numbers with many decimals

Why does the C code below output "Difference: 0.000000" ? I need to make calculations with many decimals in one of my university tasks and I don't understand this because I'm new to programming in C. Am I using the correct type? Thanks in advance.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
int main() {
long double a = 1.00000001;
long double b = 1.00000000;
long double difference = a-b;
printf("Difference: %Lf", difference);
}
I have tried that code and I'm expecting to get the result: "Difference: 0.00000001"
You see 0.000000 because %Lf prints a fixed number of decimal places, and the default number is 6. In your case, the difference is 1 in the 8th decimal place, which shows as 0.000000 when printed to 6 d.p. Either use %Le or %Lg or specify more precision: %.8Lf.
#include <stdio.h>
int main(void)
{
long double a = 1.00000001;
long double b = 1.00000000;
long double difference = a - b;
printf("Difference: %Lf\n", difference);
printf("Difference: %.8Lf\n", difference);
printf("Difference: %Le\n", difference);
printf("Difference: %Lg\n", difference);
return 0;
}
Note the minimal set of headers.
Output:
Difference: 0.000000
Difference: 0.00000001
Difference: 1.000000e-08
Difference: 1e-08
#include <stdio.h>
int main() {
long double a = 1.000000001;
long double b = 1.000000000;
long double difference = a-b;
printf("Difference: %.9Lf\n", difference);
}
Try this code. Actually, you need to specify to the compiler how much precision you need after the decimal point. Here the .9 will print 9 digits after the decimal point. You can adjust this value according to your needs; just don't exceed the range of the variable.

C language, methods to perform simple calculations without using floating point numbers

Are there any methods, code snippets or libraries to perform simple calculations (multiplications, divisions, sums, subtractions) without using floating point numbers?
I code in C on an 8 bits MCU without Floating Point Unit, so floating calculations are very long. I would like to convert all my floating point calculations to integers.
I can allow doing float calculations at initialization for example to calculate integer coefficients from float coefficients.
Scale your integers by using one or two digits as the fractional part. For example, 345 can be interpreted as 3.45. All arithmetic is (almost) exactly the same.
Example:
int mult(int a, int b)
{
long long result = ((long long)a * b) / 100;
if(result > INT_MAX || result < INT_MIN) { /* do something */}
return result;
}
int divide(int a, int b)
{
return b ? ((long long)a * 100) / b : 0;
}
int main(void)
{
int result = divide(500, 3000);
printf("%d.%d\n", result / 100, result % 100);
}

How to make the sum of two functions on the right side for function object?

I have some code for numerical integration, it works fine, but I have a little question.
Here is my main.c code:
#include <math.h>
#include <stdio.h>
#include "integral.h"
double func(double x) {
return sin(x) + cos(x);
}
int main(void) {
double a = 0;
double b = 1;
int steps = 5;
double (*f)(double x);
f = func;
double i = integrate(f, a, b, steps);
printf("%lf", i);
}
And this is how my integration function looks like:
double integrate(double(*f)(double x), double a, double b, int steps);
So, my question: is there any way to code look like this[without func()]:
double a = 0;
double b = 1;
int steps = 5;
double (*f)(double x);
f = sin + cos;
double i = integrate(f, a, b, steps);
Not in C :).
That + is a pretty high-level construct, usually called an "operator". To do what you're asking, you'd need a way to redefine builtin syntax. When the compiler sees +, it would look up the meaning of that symbol, based on the arguments on either side. In C++ you'd write an operator+ method, in Python an __add__ method, in Rust you'd impl Add, and so on for other languages.
But unfortunately, there are no such niceties in C. Or fortunately, depending on your stance, since the above can get very complicated very quickly. C is, for better or worse, small, simple, dangerous, and fast.

Trouble when computing modulos with floats in C

I am not an expert in programming, and I am facing the following issue.
I need to compute modulo between floats A and B.
So I use fmod((double)A, (double)B).
Theorically, if A is a multiple of B, then the result is 0.0.
However, due to floating point precision purpose, A and B are not exactly the number I expected to have.
Then, the result of the modulo computation is not 0.0, but something different.
Which is problematic.
Example:
A=99999.9, but the compiler interprets it as 99999.898.
B=99.9, but the compiler interprets it as 99.900002.
fmod(A,B) expected to be 0.0, but gives actually 99.9.
So the question is: how do you use to manage this kind of situation ?
Thank you
The trouble is that:
A is not 99999.9, but 99999.8984375 and
B is not 99.9, but 99.90000152587890625 and
A mod B is 99.89691162109375
OP is getting the correct answer for the arguments given.
Need to use different augments.
A reasonable alternative is to convert the arguments by a scaled power-of-10, then round to an integer, %, back to floating point and un-scale.
Overflow is a concern.
Since OP wants to treat numbers to the nearest 0.1, scale by 10.
#include <float.h>
#include <stdio.h>
int main(void) {
float A = 99999.9;
float B = 99.9;
printf("%.25f\n", A);
printf("%.25f\n", B);
printf("%.25f\n", fmod(A,B));
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
printf("D = %.25f\n", D);
return 0;
}
Output
99999.8984375000000000000000000
99.9000015258789062500000000
99.8969116210937500000000000
D = 0.0000000000000000000000000
Alternative
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
Scale, but skip the integer conversion part
double a = round(A*10.0);
double b = round(B*10.0);
double m = fmod(a,b);
double D = m/10.0;

Is there a function to round a float in C or do I need to write my own?

Is there a function to round a float in C or do I need to write my own?
float conver = 45.592346543;
I would like to round the actual value to one decimal place, conver = 45.6.
As Rob mentioned, you probably just want to print the float to 1 decimal place. In this case, you can do something like the following:
#include <stdio.h>
#include <stdlib.h>
int main()
{
float conver = 45.592346543;
printf("conver is %0.1f\n",conver);
return 0;
}
If you want to actually round the stored value, that's a little more complicated. For one, your one-decimal-place representation will rarely have an exact analog in floating-point. If you just want to get as close as possible, something like this might do the trick:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
float conver = 45.592346543;
printf("conver is %0.1f\n",conver);
conver = conver*10.0f;
conver = (conver > (floor(conver)+0.5f)) ? ceil(conver) : floor(conver);
conver = conver/10.0f;
//If you're using C99 or better, rather than ANSI C/C89/C90, the following will also work.
//conver = roundf(conver*10.0f)/10.0f;
printf("conver is now %f\n",conver);
return 0;
}
I doubt this second example is what you're looking for, but I included it for completeness. If you do require representing your numbers in this way internally, and not just on output, consider using a fixed-point representation instead.
Sure, you can use roundf(). If you want to round to one decimal, then you could do something like: roundf(10 * x) / 10
#include <math.h>
double round(double x);
float roundf(float x);
Don't forget to link with -lm. See also ceil(), floor() and trunc().
Just to generalize Rob's answer a little, if you're not doing it on output, you can still use the same interface with sprintf().
I think there is another way to do it, though. You can try ceil() and floor() to round up and down. A nice trick is to add 0.5, so anything over 0.5 rounds up but anything under it rounds down. ceil() and floor() only work on doubles though.
EDIT: Also, for floats, you can use truncf() to truncate floats. The same +0.5 trick should work to do accurate rounding.
To print a rounded value, #Matt J well answers the question.
float x = 45.592346543;
printf("%0.1f\n", x); // 45.6
As most floating point (FP) is binary based, exact rounding to one decimal place is not possible when the mathematically correct answer is x.1, x.2, ....
To convert the FP number to the nearest 0.1 is another matter.
Overflow: Approaches that first scale by 10 (or 100, 1000, etc) may overflow for large x.
float round_tenth1(float x) {
x = x * 10.0f;
...
}
Double rounding: Adding 0.5f and then using floorf(x*10.0f + 0.5f)/10.0 returns the wrong result when the intermediate sum x*10.0f + 0.5f rounds up to a new integer.
// Fails to round 838860.4375 correctly, comes up with 838860.5
// 0.4499999880790710449 fails as it rounds to 0.5
float round_tenth2(float x) {
if (x < 0.0) {
return ceilf(x*10.0f + 0.5f)/10.0f;
}
return floorf(x*10.0f + 0.5f)/10.0f;
}
Casting to int has the obvious problem when float x is much greater than INT_MAX.
Using roundf() and family, available in <math.h> is the best approach.
float round_tenthA(float x) {
double x10 = 10.0 * x;
return (float) (round(x10)/10.0);
}
To avoid using double, simply test if the number needs rounding.
float round_tenthB(float x) {
const float limit = 1.0/FLT_EPSILON;
if (fabsf(x) < limit) {
return roundf(x*10.0f)/10.0f;
}
return x;
}
There is a round() function, also fround(), which will round to the nearest integer expressed as a double. But that is not what you want.
I had the same problem and wrote this:
#include <math.h>
double db_round(double value, int nsig)
/* ===============
**
** Rounds double <value> to <nsig> significant figures. Always rounds
** away from zero, so -2.6 to 1 sig fig will become -3.0.
**
** <nsig> should be in the range 1 - 15
*/
{
double a, b;
long long i;
int neg = 0;
if(!value) return value;
if(value < 0.0)
{
value = -value;
neg = 1;
}
i = nsig - log10(value);
if(i) a = pow(10.0, (double)i);
else a = 1.0;
b = value * a;
i = b + 0.5;
value = i / a;
return neg ? -value : value;
}
you can use #define round(a) (int) (a+0.5) as macro
so whenever you write round(1.6) it returns 2 and whenever you write round(1.3) it return 1.

Resources