VisualStudio 和 Codeblocks 中的不同输出

问题描述 投票:0回答:1

我需要二维数组中的线性插值。 Codeblocks 中的输出是正确的,但 VisualStudio 中的输出不正确。

我有2个主要功能。

  1. 一维数组中的线性插值: 函数为 Y(X),结果为 Y(x)。

  2. 二维数组中的线性插值: 函数为 Y(X1, X2),结果为 Y(x, y)。

以及测试它的功能。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

double lin_int(int size, double* X, const double* Y, double x){
    int i;
    if (x >= *(X + size-1)){
        return *(Y + size-1);
    } else
    if (x <= *(X)){
        return *(Y);
    }
    for(i = 1; i < size; i++){
        if (*(X + i) >= x && *(X + i - 1) <= x){
            if (*(X+i) == *(X+i-1)){
                return *(Y + i - 1)+(*(Y + i)-*(Y + i - 1))*(x-*(X+i-1))/(*(X+i-1)*2); //два совпадающих значения в узлах (деление на ноль)
            }
            return *(Y + i - 1)+(*(Y + i)-*(Y + i - 1))*(x-*(X+i-1))/(*(X+i)-*(X+i-1));
        }
    }
}

/*
             |       X2[j]           y              X2[j+1]
_____________|_____________________________________________________________
X1[i]        |      Y[i][j]          x1            Y[i][j+1]
             |
x            |                     return
             |
X1[i+1]      |     Y[i+1][j]         x2           Y[i+1][j+1]
             |
X1[m]
X2[n]
Y[m][n]
*/
double lin_int_for_mass(int m, int n, double* X1, double* X2, const double* Y, double x, double y){
    int i;
    int j;
    double x1, x2;
    bool in_X1, in_X2;                                  //Проверки, что искомая точка за границей:
    if (x < *(X1) && y < *(X2)) return *Y;              //по X1 и X2 меньше оба значения x, y - возвращаем Y[0][0]
    if (x > *(X1+m) && y > *(X2+n)) return *(Y+m*n-1);  //по X1 и X2 больше оба значения x, y - возвращаем Y[m][n]
    if (x < *(X1)) x = *(X1);                           //по X1 значение x меньше X1[0] - ставим x = X1[0]
    if (y < *(X2)) y = *(X2);                           //по X2 значение y меньше X2[0] - ставим y = X2[0]
    if (x > *(X1+m-1)) x = *(X1+m-1);                   //по X1 значение x больше X1[m] - ставим x = X1[m]
    if (y > *(X2+n-1)) y = *(X2+n-1);                   //по X2 значение y больше X2[n] - ставим y = X2[n]
    for (i = 0; i < n-1; i++){
        if (x == *(X1 + i)){ //Проверка что мы в узле X1
            in_X1 = true;
            break;
        } else
        if (x > *(X1 + i) && x < *(X1 + i + 1)) break; //Если не в узле, фиксируем индекс предыдущего узла
    }
    for (j = 0; j < m-1; j++){
        if (y == *(X2 + j)){ //Проверка что мы в узле X2
            in_X2 = true;
            break;
        } else
        if (y > *(X2 + j) && y < *(X2 + j + 1)) break; //Если не в узле, фиксируем индекс предыдущего узла
    }

    if (in_X1 && in_X2) { //Если попали в два узла сетки, возвращаем уже известное значение
        return *((Y + i*n) + j);
    } else
    if (in_X1) { //Если в узле только по X1, возвращаем lin_int между узлами X2
        return lin_int(n, X2, (Y+i*n), y);
    } else
    if (in_X2) { //Если в узле только по X2, возвращаем lin_int между узлами X1
        x1 = *((Y+i*n)+j);
        x2 = *((Y+(i+1)*n)+j);
        if (*(X1+i+1) == *(X1+i)){
            return x1 + (x2-x1) * (x-*(X1+i)) / (*(X1+i)*2); //два совпадающих значения в узлах
        }
        return x1 + (x2-x1) * (x-*(X1+i)) / (*(X1+i+1) - *(X1+i));
    } else { //Если ни в какой узел не попали
        if (*(X1+i+1) == *(X1+i)){
            return x1 + (x2-x1) * (x-*(X1+i)) / (*(X1+i)*2); //два совпадающих значения в узлах
        }
        x1 = lin_int(n, X2, (Y+i*n), y); //Если не попали ни в какой узел, вычисляем x1, x2 и возвращаем lin_int между ними
        x2 = lin_int(n, X2, (Y+(i+1)*n), y);
        return x1 + (x2-x1) * (x-*(X1+i)) / (*(X1+i+1) - *(X1+i));
    }
}


void test_lin_int_mass(void){
    double X1[4] = { 0.3, 1.0, 4.0, 10.0 };
    double X2[3] = { 0.0, 90.0, 180.0 };
    double Y[4][3] =
        {/*                  0             90             180        */
        /*0.3*/            {1.0,         -0.107,         -0.5},
        /*1.0*/            {1.3,          -0.3,          -0.7},
        /*4.0*/            {1.5,          -0.2,          -0.6},
        /*10.*/            {1.53,        -0.253,         -0.5}
        };

    double i,j;
    for (i=0; i<=200; i+=15){
        printf("\t%.3lf", i);

    }
    printf("\n");
    for (i=0; i<=12; i+=1){
        printf("%.3lf", i);
        for(j=0; j<=200; j+=15){
            printf("\t%.3lf", lin_int_for_mass(4, 3, X1, X2, &Y[0][0], i, j));
        }
        printf("\n");
    }
}

int main()
{
    test_lin_int_mass();
    return 0;
}

输出不同的原因是什么?

错误的输出(在 VisualStudio 中):

    0.000   15.000  30.000  45.000  60.000  75.000  90.000  105.000 120.000 135.000 150.000 165.000 180.000 195.000
0.000   1.000   1.000   1.000   1.000   1.000   1.000   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
1.000   1.300   1.300   1.300   1.300   1.300   1.300   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
2.000   1.300   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
3.000   1.300   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
4.000   1.500   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
5.000   1.500   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
6.000   1.500   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
7.000   1.500   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
8.000   1.500   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
9.000   1.500   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
10.000  1.500   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
11.000  1.500   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500
12.000  1.500   -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500  -0.500

右输出(在代码块中):

    0.000   15.000  30.000  45.000  60.000  75.000  90.000  105.000 120.000 135.000 150.000 165.000 180.000 195.000
0.000   1.000   0.816   0.631   0.447   0.262   0.077   -0.107  -0.172  -0.238  -0.304  -0.369  -0.434  -0.500  -0.500
1.000   1.300   1.033   0.767   0.500   0.233   -0.033  -0.300  -0.367  -0.433  -0.500  -0.567  -0.633  -0.700  -0.700
2.000   1.367   1.094   0.822   0.550   0.278   0.006   -0.267  -0.333  -0.400  -0.467  -0.533  -0.600  -0.667  -0.667
3.000   1.433   1.156   0.878   0.600   0.322   0.044   -0.233  -0.300  -0.367  -0.433  -0.500  -0.567  -0.633  -0.633
4.000   1.500   1.217   0.933   0.650   0.367   0.083   -0.200  -0.267  -0.333  -0.400  -0.467  -0.533  -0.600  -0.600
5.000   1.505   1.219   0.934   0.648   0.362   0.077   -0.209  -0.271  -0.334  -0.396  -0.458  -0.521  -0.583  -0.583
6.000   1.510   1.222   0.934   0.646   0.358   0.070   -0.218  -0.276  -0.334  -0.392  -0.450  -0.508  -0.567  -0.567
7.000   1.515   1.225   0.935   0.644   0.354   0.064   -0.227  -0.280  -0.334  -0.388  -0.442  -0.496  -0.550  -0.550
8.000   1.520   1.227   0.935   0.642   0.350   0.057   -0.235  -0.285  -0.335  -0.384  -0.434  -0.484  -0.533  -0.533
9.000   1.525   1.230   0.935   0.640   0.346   0.051   -0.244  -0.290  -0.335  -0.380  -0.426  -0.471  -0.517  -0.517
10.000  1.530   1.233   0.936   0.639   0.341   0.044   -0.253  -0.294  -0.335  -0.377  -0.418  -0.459  -0.500  -0.500
11.000  1.530   1.233   0.936   0.639   0.341   0.044   -0.253  -0.294  -0.335  -0.377  -0.418  -0.459  -0.500  -0.500
12.000  1.530   1.233   0.936   0.639   0.341   0.044   -0.253  -0.294  -0.335  -0.377  -0.418  -0.459  -0.500  -0.500
c
1个回答
0
投票

函数

lin_int_for_mass()
至少在两个地方有未定义的行为:

  1. 您无需在该函数的每个路径中初始化变量
    x1
    x2
    ;特别是,如果
    in_X1
    in_X2
    都不为 true,则您可以在不初始化它们的情况下点击第 77 行中的 return 语句。
  2. 变量
    in_X1
    in_X2
    本身也是如此;你有 UB,除非对于任何 x、X1 和 i 都是
    x == *(X1 + i)
    ,对于任何 y、X2 和 j 都是
    y == *(X2 + j)

这个问题也可能出现在代码的其他地方;作为一般经验法则,避免在未初始化的情况下声明变量。除非您使用古老的语言标准,否则您不需要在函数之上声明变量,然后再分配它们(您可能会忘记这样做);您可以在需要的地方声明 初始化它们。

© www.soinside.com 2019 - 2024. All rights reserved.