Почему double - это NaN после переключения битов? - PullRequest
0 голосов
/ 16 июня 2019

Я пишу генетический алгоритм для нахождения коэффициентов с заданными точками X, Y. Принцип работы описан на этой странице - https://towardsdatascience.com/introduction-to-genetic-algorithms-including-example-code-e396e98d8bf3

У меня проблема, потому что иногда после мутации или кроссовера мое двойное значение равно NaN.

Я пытался сделать это, используя byte [] и BitArray, но в обоих подходах у меня один и тот же результат.

Преобразование двойной <-> BitArray:

public void ConvertByteArrayToCoefficients(BitArray array)
{
    Coefficients.Clear(); //Coefficients are stored in List<double>

    for (int i = 0; i < _degree + 1; i++)
    {
        var arr = array.ToByteArray();
        double value = BitConverter.ToDouble(array.ToByteArray(), i * sizeof(double));

        Coefficients.Add(value);
    }
}

public BitArray GetAllCoefficientsInBytes()
{
    BitArray bytes = new BitArray(0);

    for (int i = 0; i < Coefficients.Count; i++) //append is extension method
        bytes = bytes.Append(new BitArray(BitConverter.GetBytes(Coefficients[i])));

    return bytes;
}

Мутация:

public void Mutate(int percentageChance)
{
    BitArray bytes = GetAllCoefficientsInBytes();

    for (int i = 0; i < bytes.Length; i++)
    {
        if (_randomProvider.Next(0, 100) < percentageChance)
        {
            if (bytes.Get(i))
                bytes[i] = false;
            else
                bytes[i] = true;
         }
    }

    ConvertByteArrayToCoefficients(bytes);
}

Crossover - метод, вызываемый для каждых двух полиномов:

private void CrossoverSingle(Polynomial poly1, Polynomial poly2)
{
    int cutPosition = _randomProvider.Next(1, (_degreeOfPolynomial + 1) * sizeof(double) * 8);

    BitArray bytesOne = poly1.GetAllCoefficientsInBytes();
    BitArray bytesTwo = poly2.GetAllCoefficientsInBytes();

    for (int i = bytesOne.Length-1; i >= cutPosition; i--)
    {
        bool bitOne = bytesOne[i];
        bool bitTwo = bytesTwo[i];

        if (bitOne != bitTwo)
        {
            bytesOne[i] = bitTwo;
            bytesTwo[i] = bitOne;
        }
    }

    _crossoveredChildren.Add(new Polynomial(_randomProvider, _degreeOfPolynomial, bytesOne));
    _crossoveredChildren.Add(new Polynomial(_randomProvider, _degreeOfPolynomial, bytesTwo));
}

Весь код на github: https://github.com/Makulak/CoefficientsFinder Может быть, у вас есть идеи, почему это происходит?

1 Ответ

4 голосов
/ 16 июня 2019

Это потому, что вы используете случайные байты для генерации чисел IEEE-754. Вы не должны этого делать, потому что IEEE-754 определяет структуру для этих чисел, и использование случайного байтового ввода не даст вам случайных чисел, потому что некоторые биты представляют такие вещи, как поле is Not-a-Number, а значения NaN являются «вирусными» и делают недействительными другие вычисления. .

Для генерации случайных Double чисел вы должны использовать System.Random.NextDouble().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...