我遇到的问题是我编写的将UInt64转换为二进制数组的方法。对于某些数字,我得到的二进制表示不正确。
结果
正确 999 = 1111100111
正确 18446744073709551615 = 1111111111111111111111111111111111111111111111111111111111111111
不正确? 18446744073709551614 = 0111111111111111111111111111111111111111111111111111111111111110
根据在线转换器,二进制值18446744073709551614应为 1111111111111111111111111111111111111111111111111111111111111110
public static int[] GetBinaryArray(UInt64 n)
{
if (n == 0)
{
return new int[2] { 0, 0 };
}
var val = (int)(Math.Log(n) / Math.Log(2));
if (val == 0)
val++;
var arr = new int[val + 1];
for (int i = val, j = 0; i >= 0 && j <= val; i--, j++)
{
if ((n & ((UInt64)1 << i)) != 0)
arr[j] = 1;
else
arr[j] = 0;
}
return arr;
}
FYI :这不是家庭作业,我需要将整数转换为二进制数组以进行加密,因此需要一个位数组。我在这个网站上找到的许多解决方案将整数转换为二进制数的字符串表示,这是无用的,所以我想出了各种其他方法的混搭。
解释为什么该方法适用于某些数字而非其他数字会有所帮助。是的我使用了Math.Log并且它很慢,但性能可以在以后修复。
编辑:是的,我确实需要使用Math.Log的行,因为我的数组不会总是64位长,例如,如果我的数字是4,那么在二进制中它是100,这是数组长度3.它是我的申请要求这样做。
答案 0 :(得分:1)
输入UInt64.MaxValue - 1
的返回数组不是错误的,似乎UInt64.MaxValue
错了。
该数组长度为65个元素。这是直观错误的,因为UInt64.MaxValue
必须符合64位。
首先,不是做一个自然的日志,而是用一个日志除以基数2,你可以只做一个基于2的日志。
其次,您还需要对返回的值执行Math.Ceiling
,因为您需要将值完全适合位数。使用强制转换为int
将剩余部分丢弃意味着在声明结果数组时需要任意执行val + 1
。这仅适用于某些情况 - 其中一个不正确的是...... UInt64.MaxValue
。在必要的位数上加1可得到65个元素的数组。
第三,最后,你不能左移64位,因此在for循环初始化中i = val - 1
。
没有详尽地测试过这个......
public static int[] GetBinaryArray(UInt64 n)
{
if (n == 0)
{
return new int[2] { 0, 0 };
}
var val = (int)Math.Ceiling(Math.Log(n,2));
if (val == 0)
val++;
var arr = new int[val];
for (int i = val-1, j = 0; i >= 0 && j <= val; i--, j++)
{
if ((n & ((UInt64)1 << i)) != 0)
arr[j] = 1;
else
arr[j] = 0;
}
return arr;
}