指针相互改变,尽管它们没有关联。

huangapple go评论64阅读模式
英文:

Pointers changing eachother despite being unrelated

问题

I understand that you want me to translate the provided code and text into English. Here is the translated code and text:

#include <stdio.h>
#include <math.h>

double BrockNP(double x[]) {
    return 100 * pow(x[1] - (x[0] * x[0]), 2) + pow(1 - x[0], 2);
}
double Brock(double *vec) {
    return 100 * pow(*(vec + 1) - ((*vec) * (*vec)), 2) + pow(1 - *vec, 2);
}

double **sortSize(double *p1p, double *p2p, double *p3p, double (func)(double *));
void update(double x[], double *y);

int main() {

    double *pl, *pm, *ph;
    double **brop;
    double (*brockop)(double);

    double plarray[] = {0., 0.};
    double pmarray[] = {2., 0.};
    double pharray[] = {0., 2.};

    pl = &plarray[0], pm = &pmarray[0], ph = &pharray[0];
    brockop = &Brock;

    brop = sortSize(pl, pm, ph, brockop);

    printf("--------Before assigning to Brop values--------\n");
    printf("P_h pointer: %lf, %lf, yh = %lf\n", *ph, *(ph + 1), Brock(ph));
    printf("P_m pointer: %lf, %lf, ym = %lf\n", *pm, *(pm + 1), Brock(pm));
    printf("P_l pointer: %lf, %lf, yl = %lf\n", *pl, *(pl + 1), Brock(pl));
    printf("--------Array values before assigning to brop ------\n");
    printf("P_h array: %lf, %lf, yh = %lf\n", pharray[0], pharray[1], BrockNP(pharray));
    printf("P_m array: %lf, %lf, ym = %lf\n", pmarray[0], pmarray[1], BrockNP(pmarray));
    printf("P_l array: %lf, %lf, yl = %lf\n", plarray[0], plarray[1], BrockNP(plarray));

    pl = *brop;
    pm = *(brop + 1);
    ph = *(brop + 2);

    printf("-------Pointers assigned to brop values-----\n");
    printf("P_h pointer: %lf, %lf, yh = %lf\n", *ph, *(ph + 1), Brock(ph));
    printf("P_m pointer: %lf, %lf, ym = %lf\n", *pm, *(pm + 1), Brock(pm));
    printf("P_l pointer: %lf, %lf, yl = %lf\n", *pl, *(pl + 1), Brock(pl));
    printf("--------Array values after assigning to brop-------\n");
    printf("P_h array: %lf, %lf, yh = %lf\n", pharray[0], pharray[1], BrockNP(pharray));
    printf("P_m array: %lf, %lf, ym = %lf\n", pmarray[0], pmarray[1], BrockNP(pmarray));
    printf("P_l array: %lf, %lf, yl = %lf\n", plarray[0], plarray[1], BrockNP(plarray));

    update(pmarray, *(brop + 1)); // This seems to set pharray and pmarray to the same array
    printf("------------P_m updated--------\n");
    printf("P_h pointer: %lf, %lf, yh = %lf\n", *ph, *(ph + 1), Brock(ph));
    printf("P_m pointer: %lf, %lf, ym = %lf\n", *pm, *(pm + 1), Brock(pm));
    printf("P_l pointer: %lf, %lf, yl = %lf\n", *pl, *(pl + 1), Brock(pl);

    update(pharray, *(brop + 2));
    printf("------------P_h updated--------\n");
    printf("P_h pointer: %lf, %lf, yh = %lf\n", *ph, *(ph + 1), Brock(ph));
    printf("P_m pointer: %lf, %lf, ym = %lf\n", *pm, *(pm + 1), Brock(pm));
    printf("P_l pointer: %lf, %lf, yl = %lf\n", *pl, *(pl + 1), Brock(pl);

    update(plarray, *brop);
    printf("----------Arrays updated-----------\n");
    printf("P_h: %lf, %lf, yh = %lf\n", *ph, *(ph + 1), Brock(ph));
    printf("P_m: %lf, %lf, ym = %lf\n", *pm, *(pm + 1), Brock(pm));
    printf("P_l: %lf, %lf, yl = %lf\n", *pl, *(pl + 1), Brock(pl));
    printf("after sorting\n");

    return 0;
}

double **sortSize(double *p1p, double *p2p, double *p3p, double (func)(double *)) {

    static double *order[3];
    double bp1 = func(p1p);
    double bp2 = func(p2p);
    double bp3 = func(p3p);
    double brocks[] = {bp1, bp2, bp3};

    order[2] = ((bp1 > bp2 && bp1 > bp3) ? p1p : (bp2 > bp3) ? p2p : p3p);
    order[0] = ((bp1 < bp2 && bp1 < bp3) ? p1p : (bp2 < bp3) ? p2p : p3p);
    order[1] = ((bp1 != func(order[0]) && bp1 != func(order[2])) ? p1p : (bp2 != func(order[0]) && bp2 != func(order[2])) ? p2p : p3p);

    return order;
}

void update(double x[], double *y) {
    x[0] = *y;
    x[1] = *(y + 1);
}

I hope this helps! If you have any further questions or need assistance with anything else, please let me know.

英文:

I am trying to use the Simplex Downhill method for finding the minimum of a function. I take three points as arrays of two values and assign each a pointer so that I can order them high-to-low according to their output of some function (Rosenbrock's parabolic valley in this case). After ordering these pointers I attempt to update the arrays with the respective values, however both the high and medium point take the same value unless the points were already in the correct order.

I set the three arrays and their respective pointers,

double plarray[] = {0., 0.};
double pmarray[] = {2., 0.};
double pharray[] = {0., 2.};
double *pl, *pm, *ph;
pl = &amp;plarray[0], pm = &amp;pmarray[0], ph = &amp;pharray[0];

and sort the pointers as above. This bit works well, however when I try to replace the arrays with the proper values using this function,

void update(double x[], double *y){
x[0] = *y;
x[1] = *(y+1);
}

both pmarray and pharray take on the same values. I've tried swapping them around but it doesn't seem to change anything. Interestingly, plarray seems to work perfectly fine regardless of update order.

Brop (array of pointers sorted from lowest to highest in terms of their Brock output) is sorted as such where brockop points to Brock. sortSize sorts the pointers given by the given function,

brop = sortSize(pl, pm, ph,  brockop);
double ** sortSize(double * p1p, double * p2p, double * p3p, double (func)(double *)){
static double * order[3];
double bp1 = func(p1p);
double bp2 = func(p2p);
double bp3 = func(p3p);
double brocks[] = {bp1, bp2, bp3};
order[2] = ((bp1 &gt; bp2 &amp;&amp; bp1 &gt; bp3)? p1p: (bp2 &gt; bp3)? p2p:p3p);
order[0] = ((bp1 &lt; bp2 &amp;&amp; bp1 &lt; bp3)? p1p: (bp2 &lt; bp3)? p2p:p3p);
order[1] = ((bp1 != func(order[0]) &amp;&amp; bp1 != func(order[2]))? p1p: (bp2 != func(order[0]) &amp;&amp; bp2 != func(order[2]))? p2p: p3p);
return order;
}

I then assign the pointers to the sorted values in brop,

pl = *brop;
pm = *(brop + 1);
ph = *(brop + 2);

Please note that brop is an array of the pointers to the points of the function I wanted to sort, not a point itself.

I have some output after adding a bunch of printf for debugging,

y of Brop[0], (0.000000, 0.000000) = 1.000000
y of Brop[1], (-1.000000, 1.500000) = 29.000000
y of Brop[2], (0.000000, 2.000000) = 401.000000
--------Before assigning to Brop values--------
P_h pointer: -1.000000, 1.500000, yh = 29.000000
P_m pointer: 0.000000, 2.000000, ym = 401.000000
P_l pointer: 0.000000, 0.000000, yl = 1.000000
--------Array values before assigning to brop ------
P_h array: -1.000000, 1.500000, yh = 29.000000
P_m array: 0.000000, 2.000000, ym = 401.000000
P_l array: 0.000000, 0.000000, yl = 1.000000
-------Pointers asigned to brop values-----
P_h pointer: 0.000000, 2.000000, yh = 401.000000
P_m pointer: -1.000000, 1.500000, ym = 29.000000
P_l pointer: 0.000000, 0.000000, yl = 1.000000
--------Array values after assigning to brop-------
P_h array: -1.000000, 1.500000, yh = 29.000000
P_m array: 0.000000, 2.000000, ym = 401.000000
P_l array: 0.000000, 0.000000, yl = 1.000000
------------P_m updated--------
P_h pointer: -1.000000, 1.500000, yh = 29.000000
P_m pointer: -1.000000, 1.500000, ym = 29.000000
P_l pointer: 0.000000, 0.000000, yl = 1.000000
------------P_h updated--------
P_h pointer: -1.000000, 1.500000, yh = 29.000000
P_m pointer: -1.000000, 1.500000, ym = 29.000000
P_l pointer: 0.000000, 0.000000, yl = 1.000000
----------Arrays updated-----------
P_h: -1.000000, 1.500000, yh = 29.000000
P_m: -1.000000, 1.500000, ym = 29.000000
P_l: 0.000000, 0.000000, yl = 1.000000

Code used to produce debug output:

printf(&quot;--------Before assigning to Brop values--------\n&quot;);
printf(&quot;P_h pointer: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m pointer: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l pointer: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
printf(&quot;--------Array values before assigning to brop ------\n&quot;);
printf(&quot;P_h array: %lf, %lf, yh = %lf\n&quot;, pharray[0], pharray[1], BrockNP(pharray));
printf(&quot;P_m array: %lf, %lf, ym = %lf\n&quot;, pmarray[0], pmarray[1], BrockNP(pmarray));
printf(&quot;P_l array: %lf, %lf, yl = %lf\n&quot;, plarray[0], plarray[1], BrockNP(plarray));
pl = *brop;
pm = *(brop + 1);
ph = *(brop + 2);
printf(&quot;-------Pointers asigned to brop values-----\n&quot;);
printf(&quot;P_h pointer: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m pointer: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l pointer: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
printf(&quot;--------Array values after assigning to brop-------\n&quot;);
printf(&quot;P_h array: %lf, %lf, yh = %lf\n&quot;, pharray[0], pharray[1], BrockNP(pharray));
printf(&quot;P_m array: %lf, %lf, ym = %lf\n&quot;, pmarray[0], pmarray[1], BrockNP(pmarray));
printf(&quot;P_l array: %lf, %lf, yl = %lf\n&quot;, plarray[0], plarray[1], BrockNP(plarray));
update(pmarray, *(brop + 1));
printf(&quot;------------P_m updated--------\n&quot;);
printf(&quot;P_h pointer: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m pointer: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l pointer: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
update(pharray, *(brop+2));
printf(&quot;------------P_h updated--------\n&quot;);
printf(&quot;P_h pointer: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m pointer: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l pointer: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
update(plarray, *brop);
printf(&quot;----------Arrays updated-----------\n&quot;);
printf(&quot;P_h: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
printf(&quot;after sorting\n&quot;);

Function used for y-values:

double Brock(double * vec){
return 100*pow(*(vec+1) - ((*vec)*(*vec)), 2) + pow(1 - *vec, 2);
}

Minimal Reproducible Example:

#include &lt;stdio.h&gt;
#include &lt;math.h&gt;
double BrockNP(double x[]){
return 100*pow(x[1] - (x[0]*x[0]), 2) + pow(1 - x[0], 2);
}	
double Brock(double * vec){
return 100*pow(*(vec+1) - ((*vec)*(*vec)), 2) + pow(1 - *vec, 2);
}
double ** sortSize(double * p1p, double * p2p, double * p3p, double (func)(double *));
void update(double x[], double *y);
int main(){
double *pl, *pm, *ph;
double **brop;
double (*brockop)(double *);
double plarray[] = {0., 0.};
double pmarray[] = {2., 0.};
double pharray[] = {0., 2.};
pl = &amp;plarray[0], pm = &amp;pmarray[0], ph = &amp;pharray[0];
brockop = &amp;Brock;
brop = sortSize(pl, pm, ph,  brockop);
printf(&quot;--------Before assigning to Brop values--------\n&quot;);
printf(&quot;P_h pointer: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m pointer: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l pointer: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
printf(&quot;--------Array values before assigning to brop ------\n&quot;);
printf(&quot;P_h array: %lf, %lf, yh = %lf\n&quot;, pharray[0], pharray[1], BrockNP(pharray));
printf(&quot;P_m array: %lf, %lf, ym = %lf\n&quot;, pmarray[0], pmarray[1], BrockNP(pmarray));
printf(&quot;P_l array: %lf, %lf, yl = %lf\n&quot;, plarray[0], plarray[1], BrockNP(plarray));
pl = *brop;
pm = *(brop + 1);
ph = *(brop + 2);
printf(&quot;-------Pointers asigned to brop values-----\n&quot;);
printf(&quot;P_h pointer: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m pointer: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l pointer: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
printf(&quot;--------Array values after assigning to brop-------\n&quot;);
printf(&quot;P_h array: %lf, %lf, yh = %lf\n&quot;, pharray[0], pharray[1], BrockNP(pharray));
printf(&quot;P_m array: %lf, %lf, ym = %lf\n&quot;, pmarray[0], pmarray[1], BrockNP(pmarray));
printf(&quot;P_l array: %lf, %lf, yl = %lf\n&quot;, plarray[0], plarray[1], BrockNP(plarray));
update(pmarray, *(brop + 1));      //This seems to set pharray and pmarray to the same array
printf(&quot;------------P_m updated--------\n&quot;);
printf(&quot;P_h pointer: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m pointer: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l pointer: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
update(pharray, *(brop+2));
printf(&quot;------------P_h updated--------\n&quot;);
printf(&quot;P_h pointer: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m pointer: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l pointer: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
update(plarray, *brop);
printf(&quot;----------Arrays updated-----------\n&quot;);
printf(&quot;P_h: %lf, %lf, yh = %lf\n&quot;, *ph, *(ph+1), Brock(ph));
printf(&quot;P_m: %lf, %lf, ym = %lf\n&quot;, *pm, *(pm+1), Brock(pm));
printf(&quot;P_l: %lf, %lf, yl = %lf\n&quot;, *pl, *(pl+1), Brock(pl));
printf(&quot;after sorting\n&quot;);    
return 0;
}
double ** sortSize(double * p1p, double * p2p, double * p3p, double (func)(double *)){
static double * order[3];
double bp1 = func(p1p);
double bp2 = func(p2p);
double bp3 = func(p3p);
double brocks[] = {bp1, bp2, bp3};
order[2] = ((bp1 &gt; bp2 &amp;&amp; bp1 &gt; bp3)? p1p: (bp2 &gt; bp3)? p2p:p3p);
order[0] = ((bp1 &lt; bp2 &amp;&amp; bp1 &lt; bp3)? p1p: (bp2 &lt; bp3)? p2p:p3p);
order[1] = ((bp1 != func(order[0]) &amp;&amp; bp1 != func(order[2]))? p1p: (bp2 != func(order[0]) &amp;&amp; bp2 != func(order[2]))? p2p: p3p);
return order;
}
void update(double x[], double *y){
x[0] = *y;
x[1] = *(y+1);
}

Any help would be much appreciated.

Edit: brop is just the array of pointers in size order as above.

答案1

得分: 3

我理解你的要求,以下是代码部分的翻译:

If we simplify your code down to the absolute minimum (using just two doubles instead of three arrays), you'll see that you do the equivalent of this:

如果我们将你的代码简化到绝对最小(只使用两个 double 变量而不是三个数组),你会发现你所做的等同于以下操作:

double x = 42, y = 43;
double *px = &y, *py = &x; // !! notice that these are swapped !!
x = *px; // A
y = *py; // B

这里的操作 A 会覆盖 x 的值。因此,即使 py 指向 x,在代码执行到操作 B 时,x 的原始值已经丢失,所以 y 将被设置为 43,因为这是存储在 x 中的值。

There are multiple ways to solve this:

有多种方法可以解决这个问题:

  • create a copy of your three arrays, apply the permutation, and then copy back,

  • sort your points in-place by swapping values between the three arrays in your sort function, or

  • always use the pointers pl, pm, ph instead of the original arrays. So you won't need to copy things around at all.

  • 创建三个数组的副本,应用排列,然后复制回来,

  • 通过在排序函数中在三个数组之间交换值来原地对点进行排序,

  • 始终使用指针 plpmph 而不是原始数组。这样,你就不需要复制数据。

The first is probably the simplest fix to the existing code:

第一种方法可能是对现有代码的最简单修复:

double plarray[] = {0., 0.};
double pmarray[] = {2., 0.};
double pharray[] = {0., 2.};

// ... sort ...

pl = brop[0];
pm = brop[1];
ph = brop[2];
double tmp_plarray[2];
double tmp_pmarray[2];
double tmp_pharray[2];

// apply permutation into temporary arrays
update(tmp_plarray, pl);
update(tmp_pmarray, pm);
update(tmp_pharray, ph);

// copy back into original arrays
update(plarray, tmp_plarray);
update(pmarray, tmp_pmarray);
update(pharray, tmp_pharray);

Though I'd recommend going with the 3rd as it will simplify a lot of your code greatly while simultaneously being faster.

但我建议选择第三种方法,因为它将大大简化你的代码,同时也更快。

英文:

If we simplify your code down to the absolute minimum (using just two doubles instead of three arrays), you'll see that you do the equivalent of this:

double x = 42, y = 43;
double *px = &amp;y, *py = &amp;x; // !! notice that these are swapped !!
x = *px; // A
y = *py; // B

Line A here overwrites the value of x. So even though py points to x, the original value of x is already lost, so y will be set to 43 because that's what's stored in x when the code reaches line B.

There are multiple ways to solve this:

  • create a copy of your three arrays, apply the permutation, and then copy back,
  • sort your points in-place by swapping values between the three arrays in your sort function, or
  • always use the pointers pl, pm, ph instead of the original arrays. So you won't need to copy things around at all.

The first is probably the simplest fix to the existing code:

double plarray[] = {0., 0.};
double pmarray[] = {2., 0.};
double pharray[] = {0., 2.};
// ... sort ...
pl = brop[0];
pm = brop[1];
ph = brop[2];
double tmp_plarray[2];
double tmp_pmarray[2];
double tmp_pharray[2];
// apply permutation into temporary arrays
update(tmp_plarray, pl);
update(tmp_pmarray, pm);
update(tmp_pharray, ph);
// copy back into original arrays
update(plarray, tmp_plarray);
update(pmarray, tmp_pmarray);
update(pharray, tmp_pharray);

Though I'd recommend going with the 3rd as it will simplify a lot of your code greatly while simultaneously being faster.

huangapple
  • 本文由 发表于 2023年2月18日 00:32:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75486923.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定