C++-g++将int强制转换为double会得到负值

C++ - g++ casting int to double gives negative value

本文关键字:double int 转换 C++-g++      更新时间:2023-10-16

在windows上使用mingw进行项目:

C:Users...>g++ -dumpversion
4.5.0

当我在g++v4.2.4下编译代码时,我遇到了一个分段错误——几个小时后,我把它固定在了一行:

double decimal = ((double) rand()) / (RAND_MAX + 1);

出于某种原因,这给出了负值(一件事导致了另一件事)。什么原因?

编辑:cpp:

#include <iostream>
#include "Random.h"
#include <math.h>
using namespace std;
double Random::exponential(int T) {
    double decimal = ((double) rand()) / (RAND_MAX + 1);
    //  std::cout << "decimal : " << decimal << std::endl;
    return log(1 - decimal)*(-T);
}
//etc

h:

#ifndef RANDOM_H
#define RANDOM_H
#include <cstdlib>
#include <math.h>
class Random {
public:
    static double exponential(int T);
    static int random_int(int min, int max);
    static bool coin(); //50% true 50% false
};
#endif  /* RANDOM_H */

刚刚注意到(math.h)的双include,但这不应该是的问题

在您的情况下,RAND_MAX是存储它的整数类型的最大值,因此RAND_MAX + 1会给您最大负值。从技术上讲,这是有符号整数溢出,这是未定义的行为,所以任何事情都可能发生。

正如J-16所指出的,你需要做

double decimal = (double)rand() / ((double)RAND_MAX + 1);

在您的环境中,RAND_MAX可能设置为最高的正数,例如0x7fff(32767)。当你在其中加一个时,它实际上会绕到最低的负数,比如0x8000(-32768)。当然,这一切都假设两个是互补的,并且数字会换行,这两者都不是标准规定的)。

所以,因为你将rand的正值或零值除以负值,所以大多数时候你会得到负数,偶尔也会得到零。

您可以在除法中使用RAND_MAX而不是RAND_MAX+1。这样可以避免给你一个负数,但你会遇到另一个问题。

因为rand有可能返回RAND_MAX,所以除法的结果可能是1。当你试图计算log (1 - decimal) * (-T)时,取零的对数,你会得到一个错误:log(0)在数学中没有定义。

我建议使用这样的东西来避免这个问题:

double Random::exponential (int T) {
    int randVal = rand();
    while (randVal == RAND_MAX)
        randVal = rand();
    double decimal = (double) randVal / RAND_MAX;
    return log (1 - decimal) * (-T);
}

这将以偶尔对rand进行双重调用为代价来避免边缘情况。