C ++ - g ++ приведение int к double дает отрицательное значение - PullRequest
0 голосов
/ 20 февраля 2012

Работал над проектом с mingw на windows:

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), но это невопрос

Ответы [ 2 ]

4 голосов
/ 20 февраля 2012

В вашем случае RAND_MAX - это максимальное значение для целочисленного типа, в котором оно хранится, поэтому RAND_MAX + 1 дает максимальное отрицательное значение. Технически это целочисленное переполнение со знаком, неопределенное поведение, поэтому может произойти все что угодно.

Вы должны сделать, как указал J-16,

double decimal = (double)rand() / ((double)RAND_MAX + 1);
1 голос
/ 20 февраля 2012

В вашей среде для 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.

...