立方根の計算
Posted feedbacks - C
% ./cube_root 10 2.1544346900318895 % ./cube_root 100 4.6415888336127781
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <stdio.h>
#include <stdlib.h>
long double cube_root(long double x, long double min, long double max){
long double m = (min + max) / 2;
long double d = m * m * m - x;
if(d > -1E-13 && d < 1E-13) return m;
if(d > 0)
return cube_root(x, min, m);
else
return cube_root(x, m, max);
}
int main(int argc, char *argv[])
{
long double x, y;
if(argc < 2) return EXIT_FAILURE;
sscanf(argv[1], "%llf", &x);
y = cube_root(x, 0, 1000);
printf("%.16llf\n", y);
return EXIT_SUCCESS;
}
|
相対誤差も絶対誤差も 1e-12 以下になるようにしてみました。
浮動小数点演算の誤差は相対誤差を基本に考えた方が幸せになれるような気がしたので。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include<assert.h>
#define EPS 1e-12
double cubicrt(double x)
{
double y,oldy,z=1.0;
if(x==0.0){
return 0.0;
}
while(fabs(x)>8){
x/=8;
z*=2;
}
while(fabs(x)<0.125){
x*=8;
z/=2;
}
y=x;
do{
oldy=y;
y=2*oldy/3+x/(3*oldy*oldy);
}while(fabs(y-oldy)>fabs(EPS*oldy) || fabs(y-oldy)>EPS);
return y*z;
}
void test(double x,double y,double truey,double eps)
{
assert(fabs(y-truey)<=fabs(eps*y) && fabs(y-truey)<=eps);
return;
}
int main()
{
int i=0;
double x,y;
srand(time(NULL));
/* テスト */
for(i=0;i<1000;i++){
x=rand()*2000.0/RAND_MAX-500;
y=cubicrt(x);
test(x,y*y*y,x,EPS);
}
for(i=0;i<1000;i++){
x=rand()*2e-310/RAND_MAX-1e-310;
y=cubicrt(x);
test(x,y*y*y,x,EPS);
}
return 0;
}
|



にしお
#3411()
Rating1/1=1.00
ただし、このお題の趣旨は実数区間での探索なので、 立方根関数があっても使ってはいけません。 指数関数と対数関数も禁止します。
Pythonで表現した入出力の例:
[ reply ]