Я решил немного поэкспериментировать с complex.h и столкнулся с тем, что считаю очень любопытной проблемой.
int mandelbrot(long double complex c, int lim)
{
long double complex z = c;
for(int i = 0; i < lim; ++i, z = cpowl(z,2)+c)
{
if(creall(z)*creall(z)+cimagl(z)*cimagl(z) > 4.0)
return 0;
}
return 1;
}
int mandelbrot2(long double cr, long double ci, int lim)
{
long double zr = cr;
long double zi = ci;
for(int i = 0; i < lim; ++i, zr = zr*zr-zi*zi+cr, zi = 2*zr*zi+ci)
{
if(zr*zr+zi*zi > 4.0)
return 0;
}
return 1;
}
Эти функции не работают одинаково. Если мы введем -2.0 + 0.0i и предел выше 17, последний вернет 1, что является правильным для любого предела, тогда как первый вернет 0, по крайней мере, в моей системе. GCC 9.1.0, Ryzen 2700x.
Я не могу понять, как это может случиться. Я имею в виду, хотя я не совсем понимаю, как complex.h работает за кулисами, для этого конкретного примера не имеет смысла, что результаты должны отклоняться, как это.
Во время написания я замечаю cpowl (z, 2) + c, и попытался изменить его на z * z + c, что помогло, однако после быстрого теста я обнаружил, что поведение все еще отличается. Ex. -1,3 + 0,1 * I, lim = 18.
Мне любопытно узнать, относится ли это к моей системе и какова причина этого, хотя я прекрасно понимаю, что наиболее похожий сценарий - это ясделав ошибку, но, увы, я не могу ее найти.
--- edit ---
Наконец, полный код, включая изменения и исправления. Кажется, теперь две функции дают один и тот же результат.
#include <stdio.h>
#include <complex.h>
int mandelbrot(long double complex c, int lim)
{
long double complex z = c;
for(int i = 0; i < lim; ++i, z = z*z+c)
{
if(creall(z)*creall(z)+cimagl(z)*cimagl(z) > 4.0)
return 0;
}
return 1;
}
int mandelbrot2(long double cr, long double ci, int lim)
{
long double zr = cr;
long double zi = ci;
long double tmp;
for(int i = 0; i < lim; ++i)
{
if(zr*zr+zi*zi > 4.0) return 0;
tmp = zi;
zi = 2*zr*zi+ci;
zr = zr*zr-tmp*tmp+cr;
}
return 1;
}
int main()
{
long double complex c = -2.0+0.0*I;
printf("%i\n",mandelbrot(c,100));
printf("%i\n",mandelbrot2(-2.0,0.0,100));
return 0;
}
cpowl () все еще портит ситуацию, но, если я захочу, я мог бы просто создать свою собственную реализацию.