fmod() / modf() / frexp() / ldexp()
| Since: | C89(1989) |
|---|
These functions provide fine-grained control over floating-point numbers. They are defined in <math.h> and are used for low-level floating-point operations such as remainder calculation, splitting a value into its integer and fractional parts, and decomposing a value into its mantissa and exponent. You may need to pass the -lm linker option at compile time.
Syntax
double fmod(double x, double y); double modf(double x, double *iptr); // The absolute value of the mantissa is in the range [0.5, 1.0). double frexp(double x, int *exp); // Computes x × 2^exp (the inverse of frexp). double ldexp(double x, int exp);
Function List
| Function | Description |
|---|---|
| fmod() | Returns the floating-point remainder of a division. It is the floating-point equivalent of the integer % operator. |
| modf() | Splits a floating-point number into its integer and fractional parts. Both parts are returned as double values. |
| frexp() | Decomposes a floating-point number into its mantissa and exponent. This is a low-level operation that exposes the IEEE 754 internal representation. |
| ldexp() | Reconstructs a floating-point number from a mantissa and an exponent. It is the inverse of frexp(). |
Sample Code
sample_fmod_modf_frexp_ldexp.c
#include <stdio.h>
#include <math.h>
int main(void) {
// Use fmod to get the floating-point remainder (% only works with integers).
printf("fmod(5.7, 2.0) = %.1f\n", fmod(5.7, 2.0)); // Prints '1.7'.
printf("fmod(-5.7, 2.0) = %.1f\n", fmod(-5.7, 2.0)); // Prints '-1.7' (sign matches the dividend).
// Practical example: normalizing an angle to the range 0° to 360°.
double angle = 730.5;
double normalized = fmod(angle, 360.0);
printf("%.1f° -> normalized: %.1f°\n", angle, normalized); // Prints '10.5°'.
// Use modf to split a value into its integer and fractional parts.
double int_part;
double frac_part = modf(3.75, &int_part);
printf("3.75 integer part: %.1f, fractional part: %.2f\n", int_part, frac_part);
// Prints 'integer part: 3.0, fractional part: 0.75'.
double neg_frac = modf(-2.3, &int_part);
printf("-2.3 integer part: %.1f, fractional part: %.1f\n", int_part, neg_frac);
// The sign matches the original value: prints 'integer part: -2.0, fractional part: -0.3'.
// Use frexp to decompose a floating-point number into its mantissa and exponent.
int exp;
double mantissa = frexp(8.0, &exp);
printf("frexp(8.0): mantissa = %.4f, exponent = %d\n", mantissa, exp);
// 8.0 = 0.5 × 2^4, so it prints 'mantissa = 0.5000, exponent = 4'.
// Use ldexp to reconstruct the original value from the mantissa and exponent.
double restored = ldexp(mantissa, exp);
printf("ldexp(%.4f, %d) = %.1f\n", mantissa, exp, restored);
// Prints '8.0' (the inverse of frexp).
return 0;
}
Run the following command:
gcc fmod_modf_frexp_ldexp.c -o fmod_modf_frexp_ldexp -lm ./fmod_modf_frexp_ldexp fmod(5.7, 2.0) = 1.7 fmod(-5.7, 2.0) = -1.7 730.5° -> normalized: 10.5° 3.75 integer part: 3.0, fractional part: 0.75 -2.3 integer part: -2.0, fractional part: -0.3 frexp(8.0): mantissa = 0.5000, exponent = 4 ldexp(0.5000, 4) = 8.0
Common Mistakes
Common Mistake: Passing 0 as the Divisor to fmod
fmod(x, 0.0) returns NaN (Not a Number). Always verify that the divisor is not zero before calling the function.
fmod_zero_ng.c
#include <stdio.h>
#include <math.h>
int main(void) {
/* NG: divisor is 0, so the result is NaN. */
double ng = fmod(5.0, 0.0);
printf("fmod(5.0, 0.0) = %f\n", ng); /* Prints 'nan'. */
/* OK: verify it is not 0 before calling. */
double divisor = 2.0;
if (divisor != 0.0) {
double result = fmod(5.0, divisor);
printf("fmod(5.0, 2.0) = %.1f\n", result); /* 1.0 */
} else {
printf("Divisor is 0.\n");
}
/* Use isnan() (math.h) to check whether the result is NaN. */
if (isnan(ng)) {
printf("fmod(5.0, 0.0) is NaN.\n");
}
return 0;
}
Run the following command:
gcc fmod_zero_ng.c -o fmod_zero_ng -lm ./fmod_zero_ng fmod(5.0, 0.0) = nan fmod(5.0, 2.0) = 1.0 fmod(5.0, 0.0) is NaN.
Notes
The integer % operator cannot be used with floating-point numbers. Always use fmod() to compute the remainder of a floating-point division. It is commonly used for wrap-around calculations such as normalizing angles in game development or implementing periodic behavior.
modf() returns the integer part as a double (with a fractional part of zero). Unlike floor(), it preserves the sign of the original value for the integer part even with negative numbers (for example, the integer part of -2.3 is -2.0). If you simply want to round down, floor() is more appropriate.
frexp() and ldexp() directly manipulate the internal IEEE 754 representation of a floating-point number (its mantissa and exponent). They are rarely needed in typical applications, but play an important role in numerical computing libraries and high-precision arithmetic implementations.
The result of fmod(x, 0.0) is undefined (NaN). Always verify that the divisor is not zero before calling the function.
If you find any errors or copyright issues, please contact us.