<math.h>
MathematicsMany of the following functions have float
and long double
variants as described below (e.g. pow()
, powf()
, powl()
). The float
and long double
variants are omitted from the following table to keep your eyeballs from melting out.
Function | Description |
---|---|
acos() |
Calculate the arc cosine of a number. |
acosh() |
Compute arc hyperbolic cosine. |
asin() |
Calculate the arc sine of a number. |
asinh() |
Compute arc hyperbolic sine. |
atan() , atan2() |
Calculate the arc tangent of a number. |
atanh() |
Compute the arc hyperbolic tangent. |
cbrt() |
Compute the cube root. |
ceil() |
Ceiling—return the next whole number not smaller than the given number. |
copysign() |
Copy the sign of one value into another. |
cos() |
Calculate the cosine of a number. |
cosh() |
Compute the hyperbolic cosine. |
erf() |
Compute the error function of the given value. |
erfc() |
Compute the complementary error function of a value. |
exp() |
Compute \(e\) raised to a power. |
exp2() |
Compute 2 to a power. |
expm1() |
Compute \(e^x-1\). |
fabs() |
Compute the absolute value. |
fdim() |
Return the positive difference between two numbers clamped at 0. |
floor() |
Compute the largest whole number not larger than the given value. |
fma() |
Floating (AKA “Fast”) multiply and add. |
fmax() , fmin() |
Return the maximum or minimum of two numbers. |
fmod() |
Compute the floating point remainder. |
fpclassify() |
Return the classification of a given floating point number. |
frexp() |
Break a number into its fraction part and exponent (as a power of 2). |
hypot() |
Compute the length of the hypotenuse of a triangle. |
ilogb() |
Return the exponent of a floating point number. |
isfinite() |
True if the number is not infinite or NaN. |
isgreater() |
True if one argument is greater than another. |
isgreatereequal() |
True if one argument is greater than or equal to another. |
isinf() |
True if the number is infinite. |
isless() |
True if one argument is less than another. |
islesseequal() |
True if one argument is less than or equal to another. |
islessgreater() |
Test if a floating point number is less than or greater than another. |
isnan() |
True if the number is Not-a-Number. |
isnormal() |
True if the number is normal. |
isunordered() |
Macro returns true if either floating point argument is NaN. |
ldexp() |
Multiply a number by an integral power of 2. |
lgamma() |
Compute the natural logarithm of the absolute value of \(\Gamma(x)\). |
log() |
Compute the natural logarithm. |
log10() |
Compute the log-base-10 of a number. |
log2() |
Compute the base-2 logarithm of a number. |
logb() |
Extract the exponent of a number given FLT_RADIX . |
log1p() |
Compute the natural logarithm of a number plus 1. |
lrint() |
Returns x rounded in the current rounding direction as an integer. |
lround() , llround() |
Round a number in the good old-fashioned way, returning an integer. |
modf() |
Extract the integral and fractional parts of a number. |
nan() |
Return NAN . |
nearbyint() |
Rounds a value in the current rounding direction. |
nextafter() |
Get the next (or previous) representable floating point value. |
nexttoward() |
Get the next (or previous) representable floating point value. |
pow() |
Compute a value raised to a power. |
remainder() |
Compute the remainder IEC 60559-style. |
remquo() |
Compute the remainder and (some of the) quotient. |
rint() |
Rounds a value in the current rounding direction. |
round() |
Round a number in the good old-fashioned way. |
scalbn() , scalbln() |
Efficiently compute \(x\times r^n\), where \(r\) is FLT_RADIX . |
signbit() |
Return the sign of a number. |
sin() |
Calculate the sine of a number. |
sqrt() |
Calculate the square root of a number. |
tan() |
Calculate the tangent of a number. |
tanh() |
Compute the hyperbolic tangent. |
tgamma() |
Compute the gamma function, \(\Gamma(x)\). |
trunc() |
Truncate the fractional part off a floating point value. |
It’s your favorite subject: Mathematics! Hello, I’m Doctor Math, and I’ll be making math FUN and EASY!
[vomiting sounds]
Ok, I know math isn’t the grandest thing for some of you out there, but these are merely functions that quickly and easily do math you either know, want, or just don’t care about. That pretty much covers it.
Many of these math functions exist in three forms, each corresponding to the argument and/or return types the function uses, float
, double
, or long double
.
The alternate form for float
is made by appending f
to the end of the function name.
The alternate form for long double
is made by appending l
to the end of the function name.
For example, the pow()
function, which computes \(x^y\), exists in these forms:
double pow(double x, double y); // double
float powf(float x, float y); // float
long double powl(long double x, long double y); // long double
Remember that parameters are given values as if you assigned into them. So if you pass a double
to powf()
, it’ll choose the closest float
it can to hold the double. If the double
doesn’t fit, undefined behavior happens.
We have two exciting new types in <math.h>
:
float_t
double_t
The float_t
type is at least as accurate as a float
, and the double_t
type is at least as accurate as a double
.
The idea with these types is they can represent the most efficient way of storing numbers for maximum speed.
Their actual types vary by implementation, but can be determined by the value of the FLT_EVAL_METHOD
macro.
FLT_EVAL_METHOD |
float_t type |
double_t type |
---|---|---|
0 |
float |
double |
1 |
double |
double |
2 |
long double |
long double |
Other | Implementation-defined | Implementation-defined |
For all defined values of FLT_EVAL_METHOD
, float_t
is the least-precise type used for all floating calculations.
There are actually a number of these defined, but we’ll cover most of them in their relevant reference sections, below.
But here are a couple:
NAN
represents Not-A-Number.
Defined in <float.h>
is FLT_RADIX
: the number base used by floating point numbers. This is commonly 2
, but could be anything.
As we know, nothing can ever go wrong with math… except everything!
So there are just a couple errors that might occur when using some of these functions.
Range errors mean that some result is beyond what can be stored in the result type.
Domain errors mean that you’ve passed in an argument that doesn’t have a defined result for this function.
Pole errors mean that the limit of the function as \(x\) approaches the given argument is infinite.
Overflow errors are when the result is really large, but can’t be stored without incurring large roundoff error.
Underflow errors are like overflow errors, except with very small numbers.
Now, the C math library can do a couple things when these errors occur:
errno
to some value, or…Your system might vary on what happens. You can check it by looking at the value of the variable math_errhandling
. It will be equivalent to one of the following22:
math_errhandling |
Description |
---|---|
MATH_ERRNO |
The system uses errno for math errors. |
MATH_ERREXCEPT |
The system uses exceptions for math errors. |
MATH_ERRNO | MATH_ERREXCEPT |
The system does both! (That’s a bitwise-OR!) |
You are not allowed to change math_errhandling
.
For a fuller description on how exceptions work and their meanings, see the <fenv.h>
section.
In a nutshell, pragmas offer various ways to control the compiler’s behavior. In this case, we’re talking about controlling how C’s math library works.
In specific, we have a pragma FP_CONTRACT
that can be turned off and on.
What does it mean?
First of all, keep in mind that any operation in an expression can cause rounding error. So each step of the expression can introduce more rounding error.
But what if the compiler knows a double secret way of taking the expression you wrote and converting it to a single instruction that reduced the number of steps such that the intermediate rounding error didn’t occur?
Could it use it? I mean, the results would be different than if you let the rounding error settle each step of the way…
Because the results would be different, you can tell the compiler if you want to allow it to do this or not.
If you want to allow it:
#pragma STDC FP_CONTRACT ON
and to disallow it:
#pragma STDC FP_CONTRACT OFF
If you do this at global scope, it stays at whatever state you set it to until you change it.
If you do it at block scope, it reverts to the value outside the block when the block ends.
The initial value of the FP_CONTRACT
pragma varies from system to system.
fpclassify()
Return the classification of a given floating point number.
#include <math.h>
int fpclassify(any_floating_type x);
What kind of entity does this floating point number represent? What are the options?
We’re used to floating point numbers being regular old things like 3.14
or 3490.0001
.
But floating point numbers can also represent things like infinity. Or Not-A-Number (NAN). This function will let you know which type of floating point number the argument is.
This is a macro, so you can use it with float
, double
, long double
or anything similar.
Returns one of these macros depending on the argument’s classification:
Classification | Description |
---|---|
FP_INFINITE |
Number is infinite. |
FP_NAN |
Number is Not-A-Number (NAN). |
FP_NORMAL |
Just a regular number. |
FP_SUBNORMAL |
Number is a sub-normal number. |
FP_ZERO |
Number is zero. |
A discussion of subnormal numbers is beyond the scope of the guide, and is something that most devs go their whole lives without dealing with. In a nutshell, it’s a way to represent really small numbers that might normally round down to zero. If you want to know more, see the Wikipedia page on denormal numbers23.
Print various number classifications.
#include <stdio.h>
#include <math.h>
const char *get_classification(double n)
{
switch (fpclassify(n)) {
case FP_INFINITE: return "infinity";
case FP_NAN: return "not a number";
case FP_NORMAL: return "normal";
case FP_SUBNORMAL: return "subnormal";
case FP_ZERO: return "zero";
}
return "unknown";
}
int main(void)
{
printf(" 1.23: %s\n", get_classification(1.23));
printf(" 0.0: %s\n", get_classification(0.0));
printf("sqrt(-1): %s\n", get_classification(sqrt(-1)));
printf("1/tan(0): %s\n", get_classification(1/tan(0)));
printf(" 1e-310: %s\n", get_classification(1e-310)); // very small!
}
Output24:
1.23: normal
0.0: zero
sqrt(-1): not a number
1/tan(0): infinity 1e-310: subnormal
isfinite()
, isinf()
, isnan()
, isnormal()
, signbit()
isfinite()
, isinf()
, isnan()
, isnormal()
Return true if a number matches a classification.
#include <math.h>
int isfinite(any_floating_type x);
int isinf(any_floating_type x);
int isnan(any_floating_type x);
int isnormal(any_floating_type x);
These are helper macros to fpclassify()
. Bring macros, they work on any floating point type.
Macro | Description |
---|---|
isfinite() |
True if the number is not infinite or NaN. |
isinf() |
True if the number is infinite. |
isnan() |
True if the number is Not-a-Number. |
isnormal() |
True if the number is normal. |
For more superficial discussion on normal and subnormal numbers, see fpclassify()
.
Returns non-zero for true, and zero for false.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf(" isfinite(1.23): %d\n", isfinite(1.23)); // 1
printf(" isinf(1/tan(0)): %d\n", isinf(1/tan(0))); // 1
printf(" isnan(sqrt(-1)): %d\n", isnan(sqrt(-1))); // 1
printf("isnormal(1e-310): %d\n", isnormal(1e-310)); // 0
}
signbit()
Return the sign of a number.
#include <math.h>
int signbit(any_floating_type x);
This macro takes any floating point number and returns a value indicating the sign of the number, positive or negative.
Returns 1
if the sign is negative, otherwise 0
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%d\n", signbit(3490.0)); // 0
printf("%d\n", signbit(-37.0)); // 1
}
fpclassify()
, isfinite()
, isinf()
, isnan()
, isnormal()
, copysign()
acos()
, acosf()
, acosl()
Calculate the arc cosine of a number.
#include <math.h>
double acos(double x);
float acosf(float x);
long double acosl(long double x);
Calculates the arc cosine of a number in radians. (That is, the value whose cosine is x
.) The number must be in the range -1.0 to 1.0.
For those of you who don’t remember, radians are another way of measuring an angle, just like degrees. To convert from degrees to radians or the other way around, use the following code:
= 3.14159265358979;
pi = radians * 180 / pi;
degrees = degrees * pi / 180; radians
Returns the arc cosine of x
, unless x
is out of range. In that case, errno
will be set to EDOM and the return value will be NaN. The variants return different types.
#include <stdio.h>
#include <math.h>
int main(void)
{
double acosx;
long double ldacosx;
acosx = acos(0.2);
ldacosx = acosl(0.3L);
printf("%f\n", acosx);
printf("%Lf\n", ldacosx);
}
asin()
, atan()
, atan2()
, cos()
asin()
, asinf()
, asinl()
Calculate the arc sine of a number.
#include <math.h>
double asin(double x);
float asinf(float x);
long double asinl(long double x);
Calculates the arc sine of a number in radians. (That is, the value whose sine is x
.) The number must be in the range -1.0 to 1.0.
For those of you who don’t remember, radians are another way of measuring an angle, just like degrees. To convert from degrees to radians or the other way around, use the following code:
= 3.14159265358979;
pi = radians * 180 / pi;
degrees = degrees * pi / 180; radians
Returns the arc sine of x
, unless x
is out of range. In that case, errno
will be set to EDOM and the return value will be NaN. The variants return different types.
#include <stdio.h>
#include <math.h>
int main(void)
{
double asinx;
long double ldasinx;
asinx = asin(0.2);
ldasinx = asinl(0.3L);
printf("%f\n", asinx);
printf("%Lf\n", ldasinx);
}
acos()
, atan()
, atan2()
, sin()
atan()
, atanf()
, atanl()
, atan2()
, atan2f()
, atan2l()
Calculate the arc tangent of a number.
#include <math.h>
double atan(double x);
float atanf(float x);
long double atanl(long double x);
double atan2(double y, double x);
float atan2f(float y, float x);
long double atan2l(long double y, long double x);
Calculates the arc tangent of a number in radians. (That is, the value whose tangent is x
.)
The atan2()
variants are pretty much the same as using atan()
with y
/x
as the argument…except that atan2()
will use those values to determine the correct quadrant of the result.
For those of you who don’t remember, radians are another way of measuring an angle, just like degrees. To convert from degrees to radians or the other way around, use the following code:
= 3.14159265358979;
pi = radians * 180 / pi;
degrees = degrees * pi / 180; radians
The atan()
functions return the arc tangent of x
, which will be between PI/2 and -PI/2. The atan2()
functions return an angle between PI and -PI.
#include <stdio.h>
#include <math.h>
int main(void)
{
double atanx;
long double ldatanx;
atanx = atan(0.7);
ldatanx = atanl(0.3L);
printf("%f\n", atanx);
printf("%Lf\n", ldatanx);
atanx = atan2(7, 10);
ldatanx = atan2l(3L, 10L);
printf("%f\n", atanx);
printf("%Lf\n", ldatanx);
}
cos()
, cosf()
, cosl()
Calculate the cosine of a number.
#include <math.h>
double cos(double x)
float cosf(float x)
long double cosl(long double x)
Calculates the cosine of the value x
, where x
is in radians.
For those of you who don’t remember, radians are another way of measuring an angle, just like degrees. To convert from degrees to radians or the other way around, use the following code:
= 3.14159265358979;
pi = radians * 180 / pi;
degrees = degrees * pi / 180; radians
Returns the cosine of x
. The variants return different types.
#include <stdio.h>
#include <math.h>
int main(void)
{
double cosx;
long double ldcosx;
cosx = cos(3490.0); // round and round we go!
ldcosx = cosl(3.490L);
printf("%f\n", cosx);
printf("%Lf\n", ldcosx);
}
sin()
, sinf()
, sinl()
Calculate the sine of a number.
#include <math.h>
double sin(double x);
float sinf(float x);
long double sinl(long double x);
Calculates the sine of the value x
, where x
is in radians.
For those of you who don’t remember, radians are another way of measuring an angle, just like degrees. To convert from degrees to radians or the other way around, use the following code:
= 3.14159265358979;
pi = radians * 180 / pi;
degrees = degrees * pi / 180; radians
Returns the sine of x
. The variants return different types.
#include <stdio.h>
#include <math.h>
int main(void)
{
double sinx;
long double ldsinx;
sinx = sin(3490.0); // round and round we go!
ldsinx = sinl(3.490L);
printf("%f\n", sinx);
printf("%Lf\n", ldsinx);
}
tan()
, tanf()
, tanl()
Calculate the tangent of a number.
#include <math.h>
double tan(double x)
float tanf(float x)
long double tanl(long double x)
Calculates the tangent of the value x
, where x
is in radians.
For those of you who don’t remember, radians are another way of measuring an angle, just like degrees. To convert from degrees to radians or the other way around, use the following code:
= 3.14159265358979;
pi = radians * 180 / pi;
degrees = degrees * pi / 180; radians
Returns the tangent of x
. The variants return different types.
#include <stdio.h>
#include <math.h>
int main(void)
{
double tanx;
long double ldtanx;
tanx = tan(3490.0); // round and round we go!
ldtanx = tanl(3.490L);
printf("%f\n", tanx);
printf("%Lf\n", ldtanx);
}
acosh()
, acoshf()
, acoshl()
Compute arc hyperbolic cosine.
#include <math.h>
double acosh(double x);
float acoshf(float x);
long double acoshl(long double x);
Trig lovers can rejoice! C has arc hyperbolic cosine!
These functions return the nonnegative acosh of x
, which must be greater than or equal to 1
.
Returns the arc hyperbolic cosince in the range \([0,+\infty]\).
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("acosh 1.8 = %f\n", acosh(1.8)); // 1.192911
}
asinh()
, asinhf()
, asinhl()
Compute arc hyperbolic sine.
#include <math.h>
double asinh(double x);
float asinhf(float x);
long double asinhl(long double x);
Trig lovers can rejoice! C has arc hyperbolic sine!
These functions return the asinh of x
.
Returns the arc hyperbolic sine.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("asinh 1.8 = %f\n", asinh(1.8)); // 1.350441
}
atanh()
, atanhf()
, atanhl()
Compute the arc hyperbolic tangent.
#include <math.h>
double atanh(double x);
float atanhf(float x);
long double atanhl(long double x);
These functions compute the arc hyperbolic tangent of x
, which must be in the range \([-1,+1]\). Passing exactly \(-1\) or \(+1\) might result in a pole error.
Returns the arc hyperbolic tangent of x
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("atanh 0.5 = %f\n", atanh(0.5)); // 0.549306
}
cosh()
, coshf()
, coshl()
Compute the hyperbolic cosine.
#include <math.h>
double cosh(double x);
float coshf(float x);
long double coshl(long double x);
These functions predictably compute the hyperbolic cosine of x
. A range error might occur if x
is too large.
Returns the hyperbolic cosine of x
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("cosh 0.5 = %f\n", cosh(0.5)); // 1.127626
}
sinh()
, sinhf()
, sinhl()
Compute the hyperbolic sine.
#include <math.h>
double sinh(double x);
float sinhf(float x);
long double sinhl(long double x);
These functions predictably compute the hyperbolic sine of x
. A range error might occur if x
is too large.
Returns the hyperbolic sine of x
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("sinh 0.5 = %f\n", sinh(0.5)); // 0.521095
}
tanh()
, tanhf()
, tanhl()
Compute the hyperbolic tangent.
#include <math.h>
double tanh(double x);
float tanhf(float x);
long double tanhl(long double x);
These functions predictably compute the hyperbolic tangent of x
.
Mercifully, this is the last trig-related man page I’m going to write.
Returns the hyperbolic tangent of x
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("tanh 0.5 = %f\n", tanh(0.5)); // 0.462117
}
exp()
, expf()
, expl()
Compute \(e\) raised to a power.
#include <math.h>
double exp(double x);
float expf(float x);
long double expl(long double x);
Compute \(e^x\) where \(e\) is Euler’s number25.
The number \(e\) is named after Leonard Euler, born April 15, 1707, who is responsible, among other things, for making this reference page longer than it needed to be.
Returns \(e^x\).
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("exp(1) = %f\n", exp(1)); // 2.718282
printf("exp(2) = %f\n", exp(2)); // 7.389056
}
exp2()
, exp2f()
, exp2l()
Compute 2 to a power.
#include <math.h>
double exp2(double x);
float exp2f(float x);
long double exp2l(long double x);
These functions raise 2 to a power. Very exciting, since computers are all about twos-to-powers!
These are likely to be faster than using pow()
to do the same thing.
They support fractional exponents, as well.
A range error occurs if x
is too large.
exp2()
returns \(2^x\).
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("2^3 = %f\n", exp2(3)); // 2^3 = 8.000000
printf("2^8 = %f\n", exp2(8)); // 2^8 = 256.000000
printf("2^0.5 = %f\n", exp2(0.5)); // 2^0.5 = 1.414214
}
expm1()
, expm1f()
, expm1l()
Compute \(e^x-1\).
#include <math.h>
double expm1(double x);
float expm1f(float x);
long double expm1l(long double x);
This is just like exp()
except—plot twist!–it computes that result minus one.
For more discussion about what \(e\) is, see the exp()
man page.
If x
is giant, a range error might occur.
For small values of x
near zero, expm1(x)
might be more accurate than computing exp(x)-1
.
Returns \(e^x-1\).
frexp()
, frexpf()
, frexpl()
Break a number into its fraction part and exponent (as a power of 2).
#include <math.h>
double frexp(double value, int *exp);
float frexpf(float value, int *exp);
long double frexpl(long double value, int *exp);
If you have a floating point number, you can break it into its fractional part and exponent part (as a power of 2).
For example, if you have the number \(1234.56\), this can be represented as a multiple of a power of 2 like so:
\(1234.56=0.6028125\times2^{11}\)
And you can use this function to get the \(0.6028125\) and \(11\) parts of that equation.
As for why, I have a simple answer: I don’t know. I can’t find a use. K&R2 and everyone else I can find just says how to use it, but not why you might want to.
The C99 Rationale document says:
The functions
frexp
,ldexp
, andmodf
are primitives used by the remainder of the library.There was some sentiment for dropping them for the same reasons that
ecvt
,fcvt
, andgcvt
were dropped, but their adherents rescued them for general use. Their use is problematic: on non-binary architectures, ldexp may lose precision and frexp may be inefficient.
So there you have it. If you need it.
frexp()
returns the fractional part of value
in the range 0.5 (inclusive) to 1 (exclusive), or 0. And it stores the exponent power-of-2 in the variable pointed to by exp
.
If you pass in zero, the return value and the variable exp
points to are both zero.
#include <stdio.h>
#include <math.h>
int main(void)
{
double frac;
int expt;
frac = frexp(1234.56, &expt);
printf("1234.56 = %.7f x 2^%d\n", frac, expt);
}
Output:
1234.56 = 0.6028125 x 2^11
ilogb()
, ilogbf()
, ilogbl()
Return the exponent of a floating point number.
#include <math.h>
int ilogb(double x);
int ilogbf(float x);
int ilogbl(long double x);
This gives you the exponent of the given number… it’s a little weird, because the exponent depends on the value of FLT_RADIX
. Now, this is very often 2
—but no guarantees!
It actually returns \(\log_r|x|\) where \(r\) is FLT_RADIX
.
Domain or range errors might occur for invalid values of x
, or for return values that are outside the range of the return type.
The exponent of the absolute value of the given number, depending on FLT_RADIX
.
Specifically \(\log_r|x|\) where \(r\) is FLT_RADIX
.
If you pass in 0
, it’ll return FP_ILOGB0
.
If you pass in infinity, it’ll return INT_MAX
.
If you pass in NaN, it’ll return FP_ILOGBNAN
.
The spec goes on to say that the value of FP_ILOGB0
will be either INT_MIN
or -INT_MAX
. And the value of FP_ILOGBNAN
shall be either INT_MAX
or INT_MIN
, if that’s useful in any way.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%d\n", ilogb(257)); // 8
printf("%d\n", ilogb(256)); // 8
printf("%d\n", ilogb(255)); // 7
}
ldexp()
, ldexpf()
, ldexpl()
Multiply a number by an integral power of 2.
#include <math.h>
double ldexp(double x, int exp);
float ldexpf(float x, int exp);
long double ldexpl(long double x, int exp);
These functions multiply the given number x
by 2 raised to the exp
power.
Returns \(x\times2^{exp}\).
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("1 x 2^10 = %f\n", ldexp(1, 10));
printf("5.67 x 2^7 = %f\n", ldexp(5.67, 7));
}
Output:
1 x 2^10 = 1024.000000 5.67 x 2^7 = 725.760000
log()
, logf()
, logl()
Compute the natural logarithm.
#include <math.h>
double log(double x);
float logf(float x);
long double logl(long double x);
Natural logarithms! And there was much rejoycing.
These compute the base-\(e\) logarithm of a number, \(\log_ex\), \(\ln x\).
In other words, for a given \(x\), solves \(x=e^y\) for \(y\).
The base-\(e\) logarithm of the given value, \(\log_ex\), \(\ln x\).
#include <stdio.h>
#include <math.h>
int main(void)
{
const double e = 2.718281828459045;
printf("%f\n", log(3490.2)); // 8.157714
printf("%f\n", log(e)); // 1.000000
}
log10()
, log10f()
, log10l()
Compute the log-base-10 of a number.
#include <math.h>
double log10(double x);
float log10f(float x);
long double log10l(long double x);
Just when you thought you might have to use Laws of Logarithms to compute this, here’s a function coming out of the blue to save you.
These compute the base-\(10\) logarithm of a number, \(\log_{10}x\).
In other words, for a given \(x\), solves \(x=10^y\) for \(y\).
Returns the log base-10 of x
, \(\log_{10}x\).
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%f\n", log10(3490.2)); // 3.542850
printf("%f\n", log10(10)); // 1.000000
}
log1p()
, log1pf()
, log1pl()
Compute the natural logarithm of a number plus 1.
#include <math.h>
double log1p(double x);
float log1pf(float x);
long double log1pl(long double x);
This computes \(\log_e(1 + x)\), \(\ln(1+x)\).
This works just like calling:
(1 + x) log
except it could be more accurate for small values of x
.
So if your x
is small magnitude, use this.
Returns \(\log_e(1 + x)\), \(\ln(1+x)\).
Compute some big and small logarithm values to see the difference between log1p()
and log()
:
#include <stdio.h>
#include <float.h> // for LDBL_DECIMAL_DIG
#include <math.h>
int main(void)
{
printf("Big log1p() : %.*Lf\n", LDBL_DECIMAL_DIG-1, log1pl(9));
printf("Big log() : %.*Lf\n", LDBL_DECIMAL_DIG-1, logl(1 + 9));
printf("Small log1p(): %.*Lf\n", LDBL_DECIMAL_DIG-1, log1pl(0.01));
printf("Small log() : %.*Lf\n", LDBL_DECIMAL_DIG-1, logl(1 + 0.01));
}
Output on my system:
Big log1p() : 2.30258509299404568403
Big log() : 2.30258509299404568403
Small log1p(): 0.00995033085316808305 Small log() : 0.00995033085316809164
log2()
, log2f()
, log2l()
Compute the base-2 logarithm of a number.
#include <math.h>
double log2(double x);
float log2f(float x);
long double log2l(long double x);
Wow! Were you thinking we were done with the logarithm functions? We’re only getting started!
This one computes \(\log_2 x\). That is, computes \(y\) that satisfies \(x=2^y\).
Love me those powers of 2!
Returns the base-2 logarithm of the given value, \(\log_2 x\).
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%f\n", log2(3490.2)); // 11.769094
printf("%f\n", log2(256)); // 8.000000
}
logb()
, logbf()
, logbl()
Extract the exponent of a number given FLT_RADIX
.
#include <math.h>
double logb(double x);
float logbf(float x);
long double logbl(long double x);
This function returns the whole number portion of the exponent of the number with radix FLT_RADIX
, namely the whole number portion \(\log_r|x|\) where \(r\) is FLT_RADIX
. Fractional numbers are truncated.
If the number is subnormal26, logb()
treats it as if it were normalized.
If x
is 0
, there could be a domain error or pole error.
This function returns the whole number portion of \(\log_r|x|\) where \(r\) is FLT_RADIX
.
#include <stdio.h>
#include <float.h> // For FLT_RADIX
#include <math.h>
int main(void)
{
printf("FLT_RADIX = %d\n", FLT_RADIX);
printf("%f\n", logb(3490.2));
printf("%f\n", logb(256));
}
Output:
FLT_RADIX = 2
11.000000 8.000000
modf()
, modff()
, modfl()
Extract the integral and fractional parts of a number.
#include <math.h>
double modf(double value, double *iptr);
float modff(float value, float *iptr);
long double modfl(long double value, long double *iptr);
If you have a floating point number, like 123.456
, this function will extract the integral part (123.0
) and the fractional part (0.456
). It’s total coincidence that this is exactly the plot for the latest Jason Statham action spectacular.
Both the integral part and fractional parts keep the sign of the passed in value
.
The integral part is stored in the address pointed to by iptr
.
See the note in frexp()
regarding why this is in the library.
These functions return the fractional part of the number. The integral part is stored in the address pointed to by iptr
. Both the integral and fractional parts preserve the sign of the passed-in value
.
#include <stdio.h>
#include <math.h>
void print_parts(double x)
{
double i, f;
f = modf(x, &i);
printf("Entire number : %f\n", x);
printf("Integral part : %f\n", i);
printf("Fractional part: %f\n\n", f);
}
int main(void)
{
print_parts(123.456);
print_parts(-123.456);
}
Output:
Entire number : 123.456000
Integral part : 123.000000
Fractional part: 0.456000
Entire number : -123.456000
Integral part : -123.000000 Fractional part: -0.456000
scalbn()
, scalbnf()
, scalbnl()
scalbln()
, scalblnf()
, scalblnl()
Efficiently compute \(x\times r^n\), where \(r\) is FLT_RADIX
.
#include <math.h>
double scalbn(double x, int n);
float scalbnf(float x, int n);
long double scalbnl(long double x, int n);
double scalbln(double x, long int n);
float scalblnf(float x, long int n);
long double scalblnl(long double x, long int n);
These functions efficiently compute \(x\times r^n\), where \(r\) is FLT_RADIX
.
If FLT_RADIX
happens to be 2
(no guarantees!), then this works like exp2()
.
The name of this function should have an obvious meaning to you. Clearly they all start with the prefix “scalb” which means…
…OK, I confess! I have no idea what it means. My searches are futile!
But let’s look at the suffixes:
Suffix | Meaning |
---|---|
n |
scalbn() —exponent n is an int |
nf |
scalbnf() —float version of scalbn() |
nl |
scalbnl() —long double version of scalbn() |
ln |
scalbln() —exponent n is a long int |
lnf |
scalblnf() —float version of scalbln() |
lnl |
scalblnl() —long double version of scalbln() |
So while I’m still in the dark about “scalb”, at least I have that part down.
A range error might occur for large values.
Returns \(x\times r^n\), where \(r\) is FLT_RADIX
.
#include <stdio.h>
#include <math.h>
#include <float.h>
int main(void)
{
printf("FLT_RADIX = %d\n\n", FLT_RADIX);
printf("scalbn(3, 8) = %f\n", scalbn(2, 8));
printf("scalbnf(10.2, 20) = %f\n", scalbnf(10.2, 20));
}
Output on my system:
FLT_RADIX = 2
scalbn(3, 8) = 512.000000 scalbn(10.2, 20.7) = 10695475.200000
cbrt()
, cbrtf()
, cbrtl()
Compute the cube root.
#include <math.h>
double cbrt(double x);
float cbrtf(float x);
long double cbrtl(long double x);
Computes the cube root of x
, \(x^{1/3}\), \(\sqrt[3]{x}\).
Returns the cube root of x
, \(x^{1/3}\), \(\sqrt[3]{x}\).
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("cbrt(1729.03) = %f\n", cbrt(1729.03));
}
Output:
cbrt(1729.03) = 12.002384
fabs()
, fabsf()
, fabsl()
Compute the absolute value.
#include <math.h>
double fabs(double x);
float fabsf(float x);
long double fabsl(long double x);
These functions straightforwardly return the absolute value of x
, that is \(|x|\).
If you’re rusty on your absolute values, all it means is that the result will be positive, even if x
is negative. It’s just strips negative signs off.
Returns the absolute value of x
, \(|x|\).
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("fabs(3490.0) = %f\n", fabs(3490.0)); // 3490.000000
printf("fabs(-3490.0) = %f\n", fabs(3490.0)); // 3490.000000
}
hypot()
, hypotf()
, hypotl()
Compute the length of the hypotenuse of a triangle.
#include <math.h>
double hypot(double x, double y);
float hypotf(float x, float y);
long double hypotl(long double x, long double y);
Pythagorean Theorem27 fans rejoice! This is the function you’ve been waiting for!
If you know the lengths of the two sides of a right triangle, x
and y
, you can compute the length of the hypotenuse (the longest, diagonal side) with this function.
In particular, it computes the square root of the sum of the squares of the sides: \(\sqrt{x^2 + y^2}\).
Returns the lenght of the hypotenuse of a right triangle with side lengths x
and y
: \(\sqrt{x^2 + y^2}\).
pow()
, powf()
, powl()
Compute a value raised to a power.
#include <math.h>
double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);
Computes x
raised to the y
th power: \(x^y\).
These arguments can be fractional.
Returns x
raised to the y
th power: \(x^y\).
A domain error can occur if:
x
is a finite negative number and y
is a finite non-integerx
is zero and y
is zero.A domain error or pole error can occur if x
is zero and y
is negative.
A range error can occur for large values.
sqrt()
Calculate the square root of a number.
#include <math.h>
double sqrt(double x);
float sqrtf(float x);
long double sqrtl(long double x);
Computes the square root of a number: \(\sqrt{x}\). To those of you who don’t know what a square root is, I’m not going to explain. Suffice it to say, the square root of a number delivers a value that when squared (multiplied by itself) results in the original number.
Ok, fine—I did explain it after all, but only because I wanted to show off. It’s not like I’m giving you examples or anything, such as the square root of nine is three, because when you multiply three by three you get nine, or anything like that. No examples. I hate examples!
And I suppose you wanted some actual practical information here as well. You can see the usual trio of functions here—they all compute square root, but they take different types as arguments. Pretty straightforward, really.
A domain error occurs if x
is negative.
Returns (and I know this must be something of a surprise to you) the square root of x
: \(\sqrt{x}\).
// example usage of sqrt()
float something = 10;
double x1 = 8.2, y1 = -5.4;
double x2 = 3.8, y2 = 34.9;
double dx, dy;
printf("square root of 10 is %.2f\n", sqrtf(something));
dx = x2 - x1;
dy = y2 - y1;
printf("distance between points (x1, y1) and (x2, y2): %.2f\n",
sqrt(dx*dx + dy*dy));
And the output is:
square root of 10 is 3.16 distance between points (x1, y1) and (x2, y2): 40.54
erf()
, erff()
, erfl()
Compute the error function of the given value.
#include <math.h>
double erfc(double x);
float erfcf(float x);
long double erfcl(long double x);
These functions compute the error function28 of a value.
Returns the error function of x
:
\({\displaystyle \frac{2}{\sqrt\pi} \int_0^x e^{-t^2}\,dt}\)
Output:
-2.0: -0.995322
-1.5: -0.966105
-1.0: -0.842701
-0.5: -0.520500
0.0: 0.000000
0.5: 0.520500
1.0: 0.842701
1.5: 0.966105 2.0: 0.995322
erfc()
, erfcf()
, erfcl()
Compute the complementary error function of a value.
#include <math.h>
double erfc(double x);
float erfcf(float x);
long double erfcl(long double x);
These functions compute the complementary error function29 of a value.
This is the same as:
1 - erf(x)
A range error can occur if x
is too large.
Returns 1 - erf(x)
, namely:
\({\displaystyle \frac{2}{\sqrt\pi} \int_x^{\infty} e^{-t^2}\,dt}\)
Output:
-2.0: 1.995322
-1.5: 1.966105
-1.0: 1.842701
-0.5: 1.520500
0.0: 1.000000
0.5: 0.479500
1.0: 0.157299
1.5: 0.033895 2.0: 0.004678
lgamma()
, lgammaf()
, lgammal()
Compute the natural logarithm of the absolute value of \(\Gamma(x)\).
#include <math.h>
double lgamma(double x);
float lgammaf(float x);
long double lgammal(long double x);
Compute the natural log of the absolute value of gamma30 x
, \(\log_e|\Gamma(x)|\).
A range error can occur if x
is too large.
A pole error can occur is x
is non-positive.
Returns \(\log_e|\Gamma(x)|\).
Output:
0.5: 0.572365
1.0: 0.000000
1.5: -0.120782
2.0: 0.000000
2.5: 0.284683
3.0: 0.693147
3.5: 1.200974 4.0: 1.791759
tgamma()
, tgammaf()
, tgammal()
Compute the gamma function, \(\Gamma(x)\).
#include <math.h>
double tgamma(double x);
float tgammaf(float x);
long double tgammal(long double x);
Computes the gamma function31 of x
, \(\Gamma(x)\).
A domain or pole error might occur if x
is non-positive.
A range error might occur if x
is too large or too small.
Returns the gamma function of x
, \(\Gamma(x)\).
Output:
0.5: 1.772454
1.0: 1.000000
1.5: 0.886227
2.0: 1.000000
2.5: 1.329340
3.0: 2.000000
3.5: 3.323351 4.0: 6.000000
ceil()
, ceilf()
, ceill()
Ceiling—return the next whole number not smaller than the given number.
#include <math.h>
double ceil(double x);
float ceilf(float x);
long double ceill(long double x);
Returns the ceiling of the x
: \(\lceil{x}\rceil\).
This is the next whole number not smaller than x
.
Beware this minor dragon: it’s not just “rounding up”. Well, it is for positive numbers, but negative numbers effectively round toward zero. (Because the ceiling function is headed for the next largest whole number and \(-4\) is larger than \(-5\).)
Returns the next largest whole number larger than x
.
Notice for the negative numbers it heads toward zero, i.e. toward the next largest whole number—just like the positives head toward the next largest whole number.
printf("%f\n", ceil(4.0)); // 4.000000
printf("%f\n", ceil(4.1)); // 5.000000
printf("%f\n", ceil(-2.0)); // -2.000000
printf("%f\n", ceil(-2.1)); // -2.000000
printf("%f\n", ceil(-3.1)); // -3.000000
floor()
, floorf()
, floorl()
Compute the largest whole number not larger than the given value.
#include <math.h>
double floor(double x);
float floorf(float x);
long double floorl(long double x);
Returns the floor of the value: \(\lfloor{x}\rfloor\). This is the opposite of ceil()
.
This is the largest whole number that is not greater than x
.
For positive numbers, this is like rounding down: 4.5
becomes 4.0
.
For negative numbers, it’s like rounding up: -3.6
becomes -4.0
.
In both cases, those results are the largest whole number not bigger than the given number.
Returns the largest whole number not greater than x
: \(\lfloor{x}\rfloor\).
Note how the negative numbers effectively round away from zero, unlike the positives.
printf("%f\n", floor(4.0)); // 4.000000
printf("%f\n", floor(4.1)); // 4.000000
printf("%f\n", floor(-2.0)); // -2.000000
printf("%f\n", floor(-2.1)); // -3.000000
printf("%f\n", floor(-3.1)); // -4.000000
nearbyint()
, nearbyintf()
, nearbyintl()
Rounds a value in the current rounding direction.
#include <math.h>
double nearbyint(double x);
float nearbyintf(float x);
long double nearbyintl(long double x);
This function rounds x
to the nearest integer in the current rounding direction.
The rounding direction can be set with fesetround()
in <fenv.h>
.
nearbyint()
won’t raise the “inexact” floating point exception.
Returns x
rounded in the current rounding direction.
#include <stdio.h>
#include <math.h>
#include <fenv.h>
int main(void)
{
#pragma STDC FENV_ACCESS ON // If supported
fesetround(FE_TONEAREST); // round to nearest
printf("%f\n", nearbyint(3.14)); // 3.000000
printf("%f\n", nearbyint(3.74)); // 4.000000
fesetround(FE_TOWARDZERO); // round toward zero
printf("%f\n", nearbyint(1.99)); // 1.000000
printf("%f\n", nearbyint(-1.99)); // -1.000000
}
rint()
, lrint()
, round()
, fesetround()
, fegetround()
rint()
, rintf()
, rintl()
Rounds a value in the current rounding direction.
#include <math.h>
double rint(double x);
float rintf(float x);
long double rintl(long double x);
This works just like nearbyint()
except that is can raise the “inexact” floating point exception.
Returns x
rounded in the current rounding direction.
#include <stdio.h>
#include <math.h>
#include <fenv.h>
int main(void)
{
#pragma STDC FENV_ACCESS ON
fesetround(FE_TONEAREST);
printf("%f\n", rint(3.14)); // 3.000000
printf("%f\n", rint(3.74)); // 4.000000
fesetround(FE_TOWARDZERO);
printf("%f\n", rint(1.99)); // 1.000000
printf("%f\n", rint(-1.99)); // -1.000000
}
nearbyint()
, lrint()
, round()
, fesetround()
, fegetround()
lrint()
, lrintf()
, lrintl()
, llrint()
, llrintf()
, llrintl()
Returns x
rounded in the current rounding direction as an integer.
#include <math.h>
long int lrint(double x);
long int lrintf(float x);
long int lrintl(long double x);
long long int llrint(double x);
long long int llrintf(float x);
long long int llrintl(long double x);
Round a floating point number in the current rounding direction, but this time return an integer intead of a float. You know, just to mix it up.
These come in two variants:
lrint()
—returns long int
llrint()
—returns long long int
If the result doesn’t fit in the return type, a domain or range error might occur.
The value of x
rounded to an integer in the current rounding direction.
#include <stdio.h>
#include <math.h>
#include <fenv.h>
int main(void)
{
#pragma STDC FENV_ACCESS ON
fesetround(FE_TONEAREST);
printf("%ld\n", lrint(3.14)); // 3
printf("%ld\n", lrint(3.74)); // 4
fesetround(FE_TOWARDZERO);
printf("%ld\n", lrint(1.99)); // 1
printf("%ld\n", lrint(-1.99)); // -1
}
nearbyint()
, rint()
, round()
, fesetround()
, fegetround()
round()
, roundf()
, roundl()
Round a number in the good old-fashioned way.
#include <math.h>
double round(double x);
float roundf(float x);
long double roundl(long double x);
Rounds a number to the nearest whole value.
In case of halfsies, rounds away from zero (i.e. “round up” in magnitude).
The current rounding direction’s Jedi mind tricks don’t work on this function.
The rounded value of x
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%f\n", round(3.14)); // 3.000000
printf("%f\n", round(3.5)); // 4.000000
printf("%f\n", round(-1.5)); // -2.000000
printf("%f\n", round(-1.14)); // -1.000000
}
lround()
, nearbyint()
, rint()
, lrint()
, trunc()
lround()
, lroundf()
, lroundl()
llround()
, llroundf()
, llroundl()
Round a number in the good old-fashioned way, returning an integer.
#include <math.h>
long int lround(double x);
long int lroundf(float x);
long int lroundl(long double x);
long long int llround(double x);
long long int llroundf(float x);
long long int llroundl(long double x);
These are just like round()
except they return integers.
Halfway values round away from zero, e.g. \(1.5\) rounds to \(2\) and \(-1.5\) rounds to \(-2\).
The functions are grouped by return type:
lround()
—returns a long int
llround()
—returns a long long int
If the rounded value can’t fit in the return type, a domain or range error can occur.
Returns the rounded value of x
as an integer.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%ld\n", lround(3.14)); // 3
printf("%ld\n", lround(3.5)); // 4
printf("%ld\n", lround(-1.5)); // -2
printf("%ld\n", lround(-1.14)); // -1
}
round()
, nearbyint()
, rint()
, lrint()
, trunc()
trunc()
, truncf()
, truncl()
Truncate the fractional part off a floating point value.
#include <math.h>
double trunc(double x);
float truncf(float x);
long double truncl(long double x);
These functions just drop the fractional part of a floating point number. Boom.
In other words, they always round toward zero.
Returns the truncated floating point number.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%f\n", trunc(3.14)); // 3.000000
printf("%f\n", trunc(3.8)); // 3.000000
printf("%f\n", trunc(-1.5)); // -1.000000
printf("%f\n", trunc(-1.14)); // -1.000000
}
round()
, lround()
, nearbyint()
, rint()
, lrint()
fmod()
, fmodf()
, fmodl()
Compute the floating point remainder.
#include <math.h>
double fmod(double x, double y);
float fmodf(float x, float y);
long double fmodl(long double x, long double y);
Returns the remainder of \(\frac{x}{y}\). The result will have the same sign as x
.
Under the hood, the computation performed is:
- trunc(x / y) * y x
But it might be easier just to think of the remainder.
Returns the remainder of \(\frac{x}{y}\) with the same sign as x
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%f\n", fmod(-9.2, 5.1)); // -4.100000
printf("%f\n", fmod(9.2, 5.1)); // 4.100000
}
remainder()
, remainderf()
, remainderl()
Compute the remainder IEC 60559-style.
#include <math.h>
double remainder(double x, double y);
float remainderf(float x, float y);
long double remainderl(long double x, long double y);
This is similar to fmod()
, but not quite the same. fmod()
is probably what you’re after if you’re expecting remainders to wrap around like an odometer.
The C spec quotes IEC 60559 on how this works:
When \(y\neq0\), the remainder \(r=x\) REM \(y\) is defined regardless of the rounding mode by the mathematical relation \(r=x-ny\), where \(n\) is the integer nearest the exact value of \(x/y\); whenever \(|n-x/y|=1/2\), then \(n\) is even. If \(r=0\), its sign shall be that of \(x\).
Hope that clears it up!
OK, maybe not. Here’s the upshot:
You know how if you fmod()
something by, say 2.0
you get a result that is somewhere between 0.0
and 2.0
? And how if you just increase the number that you’re modding by 2.0
, you can see the result climb up to 2.0
and then wrap around to 0.0
like your car’s odometer?
remainder()
works just like that, except if y
is 2.0
, it wraps from -1.0
to 1.0
instead of from 0.0
to 2.0
.
In other words, the range of the function runs from -y/2
to y/2
. Contrasted to fmod()
that runs from 0.0
to y
, remainder()
’s output is just shifted down half a y
.
And zero-remainder-anything is 0
.
Except if y
is zero, the function might return zero or a domain error might occur.
The IEC 60559 result of x
-remainder-y
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%f\n", remainder(3.7, 4)); // -0.300000
printf("%f\n", remainder(4.3, 4)); // 0.300000
}
remquo()
, remquof()
, remquol()
Compute the remainder and (some of the) quotient.
#include <math.h>
double remquo(double x, double y, int *quo);
float remquof(float x, float y, int *quo);
long double remquol(long double x, long double y, int *quo);
This is a funky little thing.
First of all, the return value is the remainder, the same as the remainder()
function, so check that out.
And the quotient comes back in the quo
pointer.
Or at least some of it does. You’ll get at least 3 bits worth of the quotient.
But why?
So a couple things.
One is that the quotient of some very large floating point numbers can easily be far too gigantic to fit in even a long long unsigned int
. So some of it might very well need to be lopped off, anyway.
But at 3 bits? How’s that even useful? That only gets you from 0 to 7!
The C99 Rationale document states:
The
remquo
functions are intended for implementing argument reductions which can exploit a few low-order bits of the quotient. Note that \(x\) may be so large in magnitude relative to \(y\) that an exact representation of the quotient is not practical.
So… implementing argument reductions… which can exploit a few low-order bits… Ooookay.
CPPReference has this to say32 on the matter, which is spoken so well, I will quote wholesale:
This function is useful when implementing periodic functions with the period exactly representable as a floating-point value: when calculating \(\sin(πx)\) for a very large
x
, callingsin
directly may result in a large error, but if the function argument is first reduced withremquo
, the low-order bits of the quotient may be used to determine the sign and the octant of the result within the period, while the remainder may be used to calculate the value with high precision.
And there you have it. If you have another example that works for you… congratulations! :)
Returns the same as remainder
: The IEC 60559 result of x
-remainder-y
.
In addition, at least the lowest 3 bits of the quotient will be stored in quo
with the same sign as x/y
.
There’s a great cos()
example at CPPReference33 that covers a genuine use case.
But instead of stealing it, I’ll just post a simple example here and you can visit their site for a real one.
#include <stdio.h>
#include <math.h>
int main(void)
{
int quo;
double rem;
rem = remquo(12.75, 2.25, &quo);
printf("%d remainder %f\n", quo, rem); // 6 remainder -0.750000
}
copysign()
, copysignf()
, copysignl()
Copy the sign of one value into another.
#include <math.h>
double copysign(double x, double y);
float copysignf(float x, float y);
long double copysignl(long double x, long double y);
These functions return a number that has the magnitude of x
and the sign of y
. You can use them to coerce the sign to that of another value.
Neither x
nor y
are modified, of course. The return value holds the result.
Returns a value with the magnitude of x
and the sign of y
.
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 34.9;
double y = -999.9;
double z = 123.4;
printf("%f\n", copysign(x, y)); // -34.900000
printf("%f\n", copysign(x, z)); // 34.900000
}
nan()
, nanf()
, nanl()
Return NAN
.
#include <math.h>
double nan(const char *tagp);
float nanf(const char *tagp);
long double nanl(const char *tagp);
These functions return a quiet NaN34. It is produced as if calling strtod()
with "NAN"
(or a variant thereof) as an argument.
tagp
points to a string which could be several things, including empty. The contents of the string determine which variant of NaN might get returned depending on the implementation.
Which version of NaN? Did you even know it was possible to get this far into the weeds with something that wasn’t a number?
Case 1 in which you pass in an empty string, in which case these are the same:
("");
nan
("NAN()", NULL); strtod
Case 2 in which the string contains only digits 0-9, letters a-z, letters A-Z, and/or underscore:
("goats");
nan
("NAN(goats)", NULL); strtod
And Case 3, in which the string contains anything else and is ignored:
("!");
nan
("NAN", NULL); strtod
As for what strtod()
does with those values in parens, see the [strtod()
] reference page. Spoiler: it’s implementation-defined.
Returns the requested quiet NaN, or 0 if such things aren’t supported by your system.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%f\n", nan("")); // nan
printf("%f\n", nan("goats")); // nan
printf("%f\n", nan("!")); // nan
}
nextafter()
, nextafterf()
, nextafterl()
Get the next (or previous) representable floating point value.
#include <math.h>
double nextafter(double x, double y);
float nextafterf(float x, float y);
long double nextafterl(long double x, long double y);
As you probably know, floating point numbers can’t represent every possible real number. There are limits.
And, as such, there exists a “next” and “previous” number after or before any floating point number.
These functions return the next (or previous) representable number. That is, no floating point numbers exist between the given number and the next one.
The way it figures it out is it works from x
in the direction of y
, answering the question of “what is the next representable number from x
as we head toward y
.
Returns the next representable floating point value from x
in the direction of y
.
If x
equals y
, returns y
. And also x
, I suppose.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%.*f\n", DBL_DECIMAL_DIG, nextafter(0.5, 1.0));
printf("%.*f\n", DBL_DECIMAL_DIG, nextafter(0.349, 0.0));
}
Output on my system:
0.50000000000000011 0.34899999999999992
nexttoward()
, nexttowardf()
, nexttowardl()
Get the next (or previous) representable floating point value.
<math.h>
include
double nexttoward(double x, long double y);
float nexttowardf(float x, long double y);
long double nexttowardl(long double x, long double y);
These functions are the same as nextafter()
except the second parameter is always long double
.
Returns the same as nextafter()
except if x
equals y
, returns y
cast to the function’s return type.
#include <stdio.h>
#include <float.h>
#include <math.h>
int main(void)
{
printf("%.*f\n", DBL_DECIMAL_DIG, nexttoward(0.5, 1.0));
printf("%.*f\n", DBL_DECIMAL_DIG, nexttoward(0.349, 0.0));
}
Output on my system:
0.50000000000000011 0.34899999999999992
fdim()
, fdimf()
, fdiml()
Return the positive difference between two numbers clamped at 0.
#include <math.h>
double fdim(double x, double y);
float fdimf(float x, float y);
long double fdiml(long double x, long double y);
The positive difference between x
and y
is the difference… except if the difference is less than 0
, it’s clamped to 0
.
These functions might throw a range error.
Returns the difference of x-y
if the difference is greater than 0
. Otherwise it returns 0
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%f\n", fdim(10.0, 3.0)); // 7.000000
printf("%f\n", fdim(3.0, 10.0)); // 0.000000, clamped
}
fmax()
, fmaxf()
, fmaxl()
, fmin()
, fminf()
, fminl()
Return the maximum or minimum of two numbers.
#include <math.h>
double fmax(double x, double y);
float fmaxf(float x, float y);
long double fmaxl(long double x, long double y);
double fmin(double x, double y);
float fminf(float x, float y);
long double fminl(long double x, long double y);
Straightforwardly, these functions return the minimum or maximum of two given numbers.
If one of the numbers is NaN, the functions return the non-NaN number. If both arguments are NaN, the functions return NaN.
Returns the minimum or maximum values, with NaN handled as mentioned above.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%f\n", fmin(10.0, 3.0)); // 3.000000
printf("%f\n", fmax(3.0, 10.0)); // 10.000000
}
fma()
, fmaf()
, fmal()
Floating (AKA “Fast”) multiply and add.
#include <math.h>
double fma(double x, double y, double z);
float fmaf(float x, float y, float z);
long double fmal(long double x, long double y, long double z);
This performs the operation \((x\times{y})+z\), but does so in a nifty way. It does the computation as if it had infinite precision, and then rounds the final result to the final data type according to the current rounding mode.
Contrast to if you’d do the math yourself, where it would have rounded each step of the way, potentially.
Also some architectures have a CPU instruction to do exactly this calculation, so it can do it super quick. (If it doesn’t, it’s considerably slower.)
You can tell if your CPU supports the fast version by checking that the macro FP_FAST_FMA
is set to 1
. (The float
and long
variants of fma()
can be tested with FP_FAST_FMAF
and FP_FAST_FMAL
, respectively.)
These functions might cause a range error to occur.
Returns (x * y) + z
.
isgreater()
, isgreaterequal()
, isless()
, islessequal()
Floating point comparison macros.
#include <math.h>
int isgreater(any_floating_type x, any_floating_type y);
int isgreaterequal(any_floating_type x, any_floating_type y);
int isless(any_floating_type x, any_floating_type y);
int islessequal(any_floating_type x, any_floating_type y);
These macros compare floating point numbers. Being macros, we can pass in any floating point type.
You might think you can already do that with just regular comparison operators—and you’d be right!
One one exception: the comparison operators raise the “invalid” floating exception if one or more of the operands is NaN. These macros do not.
Note that you must only pass floating point types into these functions. Passing an integer or any other type is undefined behavior.
isgreater()
returns the result of x > y
.
isgreaterequal()
returns the result of x >= y
.
isless()
returns the result of x < y
.
islessequal()
returns the result of x <= y
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%d\n", isgreater(10.0, 3.0)); // 1
printf("%d\n", isgreaterequal(10.0, 10.0)); // 1
printf("%d\n", isless(10.0, 3.0)); // 0
printf("%d\n", islessequal(10.0, 3.0)); // 0
}
islessgreater()
, isunordered()
islessgreater()
Test if a floating point number is less than or greater than another.
#include <math.h>
int islessgreater(any_floating_type x, any_floating_type y);
This macro is similar to isgreater()
and all those, except it made the section name too long if I included it up there. So it gets its own spot.
This returns true if \(x < y\) or \(x > y\).
Even though it’s a macro, we can rest assured that x
and y
are only evaluated once.
And even if x
or y
are NaN, this will not throw an “invalid” exception, unlike the normal comparison operators.
If you pass in a non-floating type, the behavior is undefined.
Returns (x < y) || (x > y)
.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%d\n", islessgreater(10.0, 3.0)); // 1
printf("%d\n", islessgreater(10.0, 30.0)); // 1
printf("%d\n", islessgreater(10.0, 10.0)); // 0
}
isgreater()
, isgreaterequal()
, isless()
, islessequal()
, isunordered()
isunordered()
Macro returns true if either floating point argument is NaN.
#include <math.h>
int isunordered(any_floating_type x, any_floating_type y);
The spec writes:
The isunordered macro determines whether its arguments are unordered.
See? Told you C was easy!
It does also elaborate that the arguments are unordered if one or both of them are NaN.
This macro returns true if one or both of the arguments are NaN.
#include <stdio.h>
#include <math.h>
int main(void)
{
printf("%d\n", isunordered(1.0, 2.0)); // 0
printf("%d\n", isunordered(1.0, sqrt(-1))); // 1
printf("%d\n", isunordered(NAN, 30.0)); // 1
printf("%d\n", isunordered(NAN, NAN)); // 1
}
isgreater()
, isgreaterequal()
, isless()
, islessequal()
, islessgreater()