为什么在切换位后 NaN 加倍?
Why double is NaN after toggling bits?
我正在编写一种遗传算法,用于查找给定 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);
}
交叉 - 为每两个多项式调用的方法:
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
也许您知道为什么会这样?
这是因为您使用随机字节生成 IEEE-754 数字。你不应该这样做,因为 IEEE-754 定义了这些数字的结构,使用随机字节输入不会给你随机数,因为有些位代表 is Not-a-Number
字段之类的东西,而 NaN 值是 "viral"并使其他计算无效。
要生成随机 Double
数字,您应该使用 System.Random.NextDouble()
。
我正在编写一种遗传算法,用于查找给定 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);
}
交叉 - 为每两个多项式调用的方法:
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 也许您知道为什么会这样?
这是因为您使用随机字节生成 IEEE-754 数字。你不应该这样做,因为 IEEE-754 定义了这些数字的结构,使用随机字节输入不会给你随机数,因为有些位代表 is Not-a-Number
字段之类的东西,而 NaN 值是 "viral"并使其他计算无效。
要生成随机 Double
数字,您应该使用 System.Random.NextDouble()
。