【问题标题】:Some sort of issue with simple int/double operations简单的 int/double 操作的某种问题
【发布时间】:2023-01-21 04:12:17
【问题描述】:

我是 C 的新手,我试图将一段(只是稍微)不平凡的代码放在一起,我在其中使用一个数组将 atan(x) 的值存储在宽度为 dx 从 0 到 1 的容器中,然后使用矩形方法来计算 atan(x)dx 从 0 到 1 的积分。代码应该循环,同时连续减小 dx 以查看积分收敛到分析结果。我完全无法弄清楚为什么我得到了循环中大多数条目的预期输出,但是第 7/8/15 个输出的(某些数字)e+268;我想这与 int/double 铸造有关,但它的不规则性对我来说很奇怪。

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

int main() {
    int array_len = 20;
    int array_len_new;
    int num_conv = 18;
    double linspace[200];
    double conv_array[200];
    double PI = 3.142857;
    double result;
    int i;
    int j;
            
    for (i = 0; i < num_conv; i++) {
        array_len_new = array_len + 10*i;
        double dx = 1./array_len_new;
        for (j = 0; j < array_len_new; j++) {
            linspace[j] = j* 1.0/array_len_new;
            conv_array[i] += atan(linspace[j])*dx;
        }
        printf("Result for %d bins is: %e\n", array_len_new, conv_array[i]);
    }

    printf("Converged result: %e\n", (PI-log(4.))/4.0);
    return 0;
}

输出:

Result for 20 bins is: 4.190854e-001
Result for 30 bins is: 4.256883e-001
Result for 40 bins is: 4.289811e-001
Result for 50 bins is: 4.309539e-001
Result for 60 bins is: 4.322680e-001
Result for 70 bins is: 4.332061e-001
Result for 80 bins is: 2.308177e+268
Result for 90 bins is: 2.308177e+268
Result for 100 bins is: 4.348934e-001
Result for 110 bins is: 4.352511e-001
Result for 120 bins is: 4.355492e-001
Result for 130 bins is: 4.358013e-001
Result for 140 bins is: 4.360175e-001
Result for 150 bins is: 4.362047e-001
Result for 160 bins is: 2.316093e+268
Result for 170 bins is: 4.365131e-001
Result for 180 bins is: 4.366416e-001
Result for 190 bins is: 4.367566e-001
Converged result: 4.391407e-001

编辑:我发现如果我将 conv_array 的长度(只需要 18 个值,我把它变大是因为我认为这无关紧要)从 200 更改为 18,甚至 100,问题就会自行解决。为什么这可能是这样吗?

【问题讨论】:

  • 您必须使用 %lf 作为 double 的格式说明符。
  • @nomoresigsegv:%e 是用于打印 double 的适当转换规范。
  • 这不会为我重现;所有输出都在 .4 左右。您使用的是什么编译器,包括版本,您编译时使用的是什么开关,您运行的是什么系统,包括版本?
  • 当您打印每个计算值的值时,您会看到什么:array_len_newdxlinspace[j]atan(linspace[j])
  • linspaceconv_array 使用数组有什么意义?看起来您可以为这两个变量使用(和重复使用)标量 double 变量。

标签: c


【解决方案1】:

您没有初始化 conv_array 的元素。作为一个非static的局部变量,其初始值是不确定的。特别是,假设它将被零初始化是不安全的,但您的代码完全依赖于该假设。用初始化程序声明它应该有助于:

    // ...
    double linspace[200];
    double conv_array[200] = {0};
    double PI = 3.142857;
    // ...

= {0} 表示第一个元素将被初始化为 0,如果任何元素被初始化,那么那些没有显式初始化器的元素将被隐式默认初始化(为 0)。

但是,就个人而言,我根本不会在您使用conv_array 的地方使用数组,也不会在您使用linspace 的地方使用数组。

【讨论】:

    【解决方案2】:

    conv_array还没有初始化,但是你做了

    conv_array[i] += atan(linspace[j])*dx;
    

    我建议

    double conv_array[200] = { 0 };
    

    附带问题:

    double PI = 3.142857;
    

    float 可能没问题,但它不是一个非常准确的值π在与double 合作时。我建议使用

    double PI = M_PI;
    

    使用 MSVC,您还需要在它上面

    #define _USE_MATH_DEFINES
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多