C++ - g++将 int 转换为 double 给出负值

发布于 2025-01-07 08:14:10 字数 963 浏览 3 评论 0原文

在 Windows 上使用 mingw 开发一个项目:

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

当我在 g++ v 4.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的)双重包含,但这不应该是问题

Was working on a project with mingw on windows :

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

When I compiled the code under g++ v 4.2.4 I was getting a segmentation fault - after couple hours I pinned it down to the line :

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

For some reason this was giving negative values (and one thing led to another).
What reason ?

Edit : 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 */

just noticed the double include (of math.h) but this shouldn't be an issue

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

物价感观 2025-01-14 08:14:11

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

正如 J-16 指出的那样,你需要这样做:

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

In your case, RAND_MAX is the maximum value for the integer type it is stored in, so RAND_MAX + 1 gives you the maximum negative value. Technically this is signed integer overflow which is undefined behaviour so anything can happen.

You need to do, as J-16 pointed out,

double decimal = (double)rand() / ((double)RAND_MAX + 1);
梦途 2025-01-14 08:14:11

在您的环境中,RAND_MAX 可能设置为最大正数,例如 0x7fff (32767)。当您向其添加 1 时,它实际上会返回到最小的负数,例如 0x8000 (-32768)。当然,这一切都假设二进制补码,并且数字将换行,这两者都不是标准所强制的)。

因此,由于您将 rand 中的正值或零值除以负值,因此大多数情况下您会得到负数,偶尔也会得到零。

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

由于 rand 有可能返回 RAND_MAX,因此除法的结果可能为 1。然后当您尝试计算 log(1 - 小数)* (-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

In your environment, RAND_MAX is probably set to the highest positive number, such as 0x7fff (32767). When you add one to that, it actually wraps around to the lowest negative number, such as 0x8000 (-32768). This all assumes two's complement of course and that the number will wrap, neither of which are mandated by the standard).

So, because you're dividing the positive-or-zero value from rand by a negative value, you'll end up with a negative number most of the time, and zero occasionally.

You can use RAND_MAX in the division instead of RAND_MAX+1. This will avoid giving you a negative number but then you'll run into another problem.

Because there's a possibility that rand will return RAND_MAX, the division may give you a result of 1. When you then try to calculate log (1 - decimal) * (-T), that's taking the logarithm of zero and you'll end up with an error: log(0) is not defined in mathematics.

I would suggest simply avoiding that problem by using something like this:

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);
}

This will avoid the edge cases at the cost of the occasional double call to rand.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文