C - finding cube root of a negative number with pow function - c

In real world cube root for a negative number should exist:
cuberoot(-1)=-1, that means (-1)*(-1)*(-1)=-1
or
cuberoot(-27)=-3, that means (-3)*(-3)*(-3)=-27
But when I calculate cube root of a negative number in C using pow function, I get nan (not a number)
double cuber;
cuber=pow((-27.),(1./3.));
printf("cuber=%f\n",cuber);
output: cuber=nan
Is there any way to calculate cube root of a negative number in C?

7.12.7.1 The cbrt functions
Synopsis
#include <math.h>
double cbrt(double x);
float cbrtf(float x);
long double cbrtl(long double x);
Description
The cbrt functions compute the real cube root of x.
If you're curious, pow can't be used to compute cube roots because one-third is not expressible as a floating-point number. You're actually asking pow to raise -27.0 to a rational power very nearly equal to 1/3; there is no real result that would be appropriate.

there is. Remember: x^(1/3) = -(-x)^(1/3). So the following should do it:
double cubeRoot(double d) {
if (d < 0.0) {
return -cubeRoot(-d);
}
else {
return pow(d,1.0/3.0);
}
}
Written without compiling, so there may be syntax errors.
Greetings,
Jost

As Stephen Canon answered, to correct function to use in this case is cbrt(). If you don't know the exponent beforehand, you can look into the cpow() function.
#include <stdio.h>
#include <math.h>
#include <complex.h>
int main(void)
{
printf("cube root cbrt: %g\n", cbrt(-27.));
printf("cube root pow: %g\n", pow(-27., 1./3.));
double complex a, b, c;
a = -27.;
b = 1. / 3;
c = cpow(a, b);
printf("cube root cpow: (%g, %g), abs: %g\n", creal(c), cimag(c), cabs(c));
return 0;
}
prints
cube root cbrt: -3
cube root pow: -nan
cube root cpow: (1.5, 2.59808), abs: 3
Keep in mind the definition of the complex power: cpow(a, b) = cexp(b* clog(a)).

Using Newton's Method:
def cubicroot(num):
flag = 1
if num < 0:
flag = -1
num = num - num - num
x0 = num / 2.
x1 = x0 - (((x0 * x0 * x0) - num) / (3. * x0 * x0))
while(round(x0) != round(x1)):
x0 = x1
x1 = x0 - (((x0 * x0 * x0) - num) / (3. * x0 * x0))
return x1 * flag
print cubicroot(27)

Related

Sinus function using Taylor expansion

The teacher asks to remove the pi subtraction cycle in the main function. I don’t know how to write the program so that the correct results will come out for any values.
#include <stdio.h>
#include <math.h>
double sinus(double x);
int main(void) {
double a, x;
scanf("%le", & x);
a = x;
while (fabs(x) > 2 * (M_PI)) {
x = fabs(x) - 2 * (M_PI);
}
if (a > 0)
a = sinus(x);
else a = (-1) * sinus(x);
printf("%le", (double) a);
return 0;
}
double sinus(double x) {
double sum = 0, h, eps = 1.e-16;
int i = 2;
h = x;
do {
sum += h;
h *= -((x * x) / (i * (i + 1)));
i += 2;
}
while (fabs(h) > eps);
return sum;
return 0;
}
#include <stdio.h>
#include <math.h>
double sinus(double x);
int main(void)
{
double a,x;
scanf("%le",&x);
a=x;
x=fmod(fabs(x),2*(M_PI));
if(a>0)
a=sinus(x);
else a=(-1)*sinus(x);
printf("%le",(double)a);
return 0;}
double sinus(double x)
{
double sum=0, h, eps=1.e-16; int i=2;
h=x;
do{
sum+=h;
h*=-((x*x)/(i*(i+1)));
i+=2;}
while( fabs(h)>eps );
return sum;
return 0;
}
… how to write the program so that the correct results will come out for any values.
OP's loop is slow with large x and an infinfite loop with very large x:
while (fabs(x) > 2 * (M_PI)) {
x = fabs(x) - 2 * (M_PI);
}
A simple, though not high quality solution, is to use fmod() in the function itself. #Damien:
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
double sinus(double x) {
x = fmod(x, 2*M_PI); // Reduce to [-2*M_PI ... 2*M_PI]
...
Although function fmod() is not expected to inject any error, the problem is that M_PI (a rational number) is an approximation of π, (an irrational number). Using that value approximation injects error especially x near multiplies of π. This is likely OK for modest quality code.
Good range reduction is a problem as challenging as the trigonometric functions themselves.
See K.C. Ng's "ARGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit" .
OP's sinus() should use additional range reduction and trigonometric properties to get x in range [-M_PI/4 ... M_PI/4] (example) before attempting the power series solution. Otherwise, convergence is slow and errors accumulate.

why is 'fast inverse square root' slower than 1/sqrt() at extremely large float?

The following full code could compare speed of fast inverse square root with 1/sqrt(). According to this sentence in wikipedia, (i.e. The algorithm was approximately four times faster than computing the square root with another method and calculating the reciprocal via floating point division.)
But here is why I am here: it is slower than 1/sqrt(). something wrong in my code? please.
#include <stdio.h>
#include <time.h>
#include <math.h>
float FastInvSqrt (float number);
int
main ()
{
float x = 1.0e+100;
int N = 100000000;
int i = 0;
clock_t start2 = clock ();
do
{
float z = 1.0 / sqrt (x);
i++;
}
while (i < N);
clock_t end2 = clock ();
double time2 = (end2 - start2) / (double) CLOCKS_PER_SEC;
printf ("1/sqrt() spends %13f sec.\n\n", time2);
i = 0;
clock_t start1 = clock ();
do
{
float y = FastInvSqrt (x);
i++;
}
while (i < N);
clock_t end1 = clock ();
double time1 = (end1 - start1) / (double) CLOCKS_PER_SEC;
printf ("FastInvSqrt() spends %f sec.\n\n", time1);
printf ("fast inverse square root is faster %f times than 1/sqrt().\n", time2/time1);
return 0;
}
float
FastInvSqrt (float x)
{
float xhalf = 0.5F * x;
int i = *(int *) &x; // store floating-point bits in integer
i = 0x5f3759df - (i >> 1); // initial guess for Newton's method
x = *(float *) &i; // convert new bits into float
x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
return x;
}
The result is as follows:
1/sqrt() spends 0.850000 sec.
FastInvSqrt() spends 0.960000 sec.
fast inverse square root is faster 0.885417 times than 1/sqrt().
A function that reduces the domain in which it computes with precision will have less computational complexity (meaning that it can be computed faster). This can be thought of as optimizing the computation of a function's shape for a subset of its definition, or like search algorithms which each are best for a particular kind of input (No Free Lunch theorem).
As such, using this function for inputs outside the interval [0, 1] (which I suppose it was optimized / designed for) means using it in the subset of inputs where its complexity is worse (higher) than other possibly specialized variants of functions that compute square roots.
The sqrt() function you are using from the library was itself (likely) also optimized, as it has pre-computed values in a sort of LUT (which act as initial guesses for further approximations); using such a more "general function" (meaning that it covers more of the domain and tries to efficientize it by precomputation, for example; or eliminating redundant computation, but that is limited; or maximizing data reuse at run-time) has its complexity limitations, because the more choices between which precomputation to use for an interval, the more decision overhead there is; so knowing at compile-time that all your inputs to sqrt are in the interval [0, 1] would help reduce the run-time decision overhead, as you would know ahead of time which specialized approximation function to use (or you could generate specialized functions for each interval of interest, at compile-time -> see meta-programming for this).
I correct my code as follows:
1. compute random number, instead of a fixed number.
2. count time consumption inside while loop and sum of it.
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
float FastInvSqrt (float number);
int
main ()
{
float x=0;
time_t t;
srand((unsigned) time(&t));
int N = 1000000;
int i = 0;
double sum_time2=0.0;
do
{
x=(float)(rand() % 10000)*0.22158;
clock_t start2 = clock ();
float z = 1.0 / sqrt (x);
clock_t end2 = clock ();
sum_time2=sum_time2+(end2-start2);
i++;
}
while (i < N);
printf ("1/sqrt() spends %13f sec.\n\n", sum_time2/(double)CLOCKS_PER_SEC);
double sum_time1=0.0;
i = 0;
do
{
x=(float)(rand() % 10000)*0.22158;
clock_t start1 = clock ();
float y = FastInvSqrt (x);
clock_t end1 = clock ();
sum_time1=sum_time1+(end1-start1);
i++;
}
while (i < N);
printf ("FastInvSqrt() spends %f sec.\n\n", sum_time1/(double)CLOCKS_PER_SEC);
printf ("fast inverse square root is faster %f times than 1/sqrt().\n", sum_time2/sum_time1);
return 0;
}
float
FastInvSqrt (float x)
{
float xhalf = 0.5F * x;
int i = *(int *) &x; // store floating-point bits in integer
i = 0x5f3759df - (i >> 1); // initial guess for Newton's method
x = *(float *) &i; // convert new bits into float
x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
//x = x * (1.5 - xhalf * x * x); // One round of Newton's method
return x;
}
but fast inverse square root still slower that 1/sqrt().
1/sqrt() spends 0.530000 sec.
FastInvSqrt() spends 0.540000 sec.
fast inverse square root is faster 0.981481 times than 1/sqrt().

Calculating Maxwell-Boltzmann Distribution

I am trying to calculate Maxwell-Boltzmann Distribution but this code gives 0.00000, what is the problem?
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
float e=2.718228183, pi=3.14159265, m=2.66*pow(10,-23), t, k=1.38*pow(10,-23), v, result;
scanf("%f %f", &t, &v);
result = sqrt(pow( m / (2*pi*k*t), 3)) * 4 * pi * pow(v,2) * pow(e, -(m * pow(v,2)) / (2*k*t));
printf("%f", result);
}
As described in the comments, the use of float together with the reduced precision of the constants give a result that is not representable anymore as a float. Changing the data type to double alone gives two decimal digits of accuracy. If we use exp, more digits for pi and do a bit of recombination of the computations we get 12 digits of accuracy. E.g.:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
double pi = 3.1415926535897932384626433832795028842, m = 2.66e-23, k =
1.38e-23;
double t, v, v2, dkt, result;
// check omitted
scanf("%lf %lf", &t, &v);
v2 = v * v;
dkt = 2 * k * t;
result = pow(m / (pi * dkt), 3 / 2.0) * 4 * pi * v2 * exp(-(m * v2) / (dkt));
printf("%.20g\n", result);
return 0;
}
The result from Pari/GP is 8.1246636077915008261803395870165527173e-9 and the result we get with the code above is 8.1246636077914841125e-09. Without the intermediate results v2, dkt and the replacement of sqrt we got 8.1246636077914824582e-09, not much of a difference, especially with accuracy where it gained nothing.
If you want the full 16 decimal digits of accuracy you need to take the whole thing apart and take a different approach.
replace
double pi=acos(-1.);
instead of
double pi=3.1415926535897932384626433832795028842;

Division issues in C

I don't really know how to explain this (that's why the title was to vague) but I need a way to make C divide in a certain way, I need to make c divide without any decimals in the answer (besides the remainder) for example;
Instead of 5.21 / .25 = 20.84
I need this 5.21 / .25 = *20* Remainder = *.21*
I found out how to find the remainder with Fmod() but how do I find the 20?
Thanks ~
how about using implicit casts?
float k = 5.21 / .25;
int n = k;
k -= n;
results in
k = .84
n = 20
using only ints will also do the job if you don't need the remainder
int k = 5.21 / .25
will automatically truncate k and get k = 20
Use double modf(double value, double *iptr) to extract the integer portion of a FP number.
The modf functions break the argument value into integral and fractional parts, each of which has the same type and sign as the argument. C11 §7.12.6.12 2
#include <math.h>
#include <stdio.h>
int main() {
double a = 5.21;
double b = 0.25;
double q = a / b;
double r = fmod(a, b);
printf("quotient: %f\n", q);
printf("remander: %f\n", r);
double ipart;
double fpart = modf(q, &ipart);
printf("quotient i part: %f\n", ipart);
printf("quotient f part: %f\n", fpart);
return 0;
}
Output
quotient: 20.840000
remander: 0.210000
quotient i part: 20.000000
quotient f part: 0.840000
Using int is problematic due to a limited range, precision and sign issues.

Using a while loop to compute the approximation of a square root of a number

I am trying to compute the square root of a number using function containing a while loop. Within the conditions of the while loop, I want to compare the absolute value of the ratio of the two values, the guessed square root and the number, to 1. However, whenever I run the program, I keep get an infinite loop outputting 1.414214. Any help? Thanks.
// Function to calculate the absolute value of a number
#include <stdio.h>
float absoluteValue (float x)
{
if ( x < 0 )
x = -x;
return (x);
}
// Function to compute the square root of a number
float squareRoot (float x, const float epsilon)
{
float guess = 1.0;
while ( absoluteValue ((guess * guess) / x) != epsilon ) {
guess = ( (x / guess) + guess ) / 2.0;
printf("%f\n", guess);
}
return guess;
}
int main (void)
{
printf ("squareRoot (2.0) = %f\n", squareRoot (2.0, 1.0));
printf ("squareRoot (144.0) = %f\n", squareRoot (144.0, 1.0));
printf ("squareRoot (17.5) = %f\n", squareRoot (17.5, 1.0));
return 0;
}
Change this:
while ( absoluteValue ((guess * guess) / x) != epsilon ) {
To:
while ( absoluteValue ((guess * guess) / x - 1.0) > epsilon ) {
You want to keep refining your answer until it's within epsilon of the goal. You need to subtract 1.0 from the ratio, to get the difference between what you're seeing and your goal, then you want to stop once the difference is within epsilon. You don't want to keep trying if it's smaller than epsilon.
You will also want to use much smaller values for epsilon, e.g. 0.000001

Resources