gpt4 book ai didi

c# - 如何在 C# 中_直接_将基数为 10(十进制)的字符串转换为字节数组?

转载 作者:行者123 更新时间:2023-11-30 16:50:20 25 4
gpt4 key购买 nike

我希望获取可变长度的字符串输入,对其进行数字解释,并将其解析为字节数组,同时对其长度施加无限制

我已经完成了二进制和十六进制:

public static byte[] GetHexBytes(this string hex, bool preTrimmed = false)
{
if (!preTrimmed)
{
hex = hex.Trim();
if (hex.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
hex = hex.Substring(2);
else if (hex.StartsWith("16#"))
hex = hex.Substring(3);
}

if (hex.Length % 2 != 0) hex = hex.PadLeft(hex.Length + 1, '0');

return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}

public static byte[] GetBinaryBytes(this string binary, bool preTrimmed = false)
{
if (!preTrimmed)
{
binary = binary.Trim();
if (binary.StartsWith("0b", StringComparison.OrdinalIgnoreCase) || binary.StartsWith("2#"))
binary = binary.Substring(2);
}

if (binary.Length % 8 != 0) binary = binary.PadLeft(binary.Length + 8 - binary.Length % 8, '0');

return Enumerable.Range(0, binary.Length)
.Where(x => x % 8 == 0)
.Select(x => Convert.ToByte(binary.Substring(x, 8), 2))
.ToArray();
}

public static byte[] GetDecimalBytes(this string dec, bool preTrimmed = false)
{
if (!preTrimmed)
{
dec = dec.Trim();
if (dec.StartsWith("10#"))
dec = dec.Substring(3);
}

//???
}

是否有可能以正向方式进行这种转换,类似于十六进制和二进制版本(从字符串的开头开始,向前计算)?

如果不是,是否可以在不使用 System.Numerics 或 BigInteger 之类的东西(从字符串手动执行)的情况下以不对字符串的长度施加任何限制的方式反向工作?

我希望它能够处理任何字符串长度,最大为 C# 的最大字符串长度 (1,073,741,823)。

例子

"FF".GetHexBytes() => [ 0xFF ]
"11111111".GetBinaryBytes() => [ 0xFF ]
"255".GetDecimalBytes() => [ 0xFF ]

"FFFF".GetHexBytes() => [ 0xFF, 0xFF ]
"1111111111111111".GetBinaryBytes() => [ 0xFF, 0xFF ]
"65535".GetDecimalBytes() => [ 0xFF, 0xFF ]

最佳答案

我忍不住为这个问题构建了一个可行的解决方案。但是,正如我已经评论过的那样,直接 调用该方法有点言过其实,所提供的代码在输入验证方面更差,效率也不高。

我的基本做法如下:

  1. 将每个数字转换为从零开始的位索引列表,与数字的索引位置相关联
  2. 根据数字位置变换位索引列表
    • 使用的方法:value * 10 == value * (8 + 2) == (value << 3) + (value << 1)
  3. 通过消除两个相等的索引值并添加它们的后继值(按位加法)来汇总位索引

理论上最后应用一次位加法就足够了,但实际上需要中间压缩以避免大数的内存不足异常

// example input
string input = "6524562164126412641206685";

var result = input
// interpret the string as a list of digits with position
.Reverse()
// transfer from list of positioned digits to list of actual bit positions,
// by repeatedly multiplying with 10
// the resulting bits need to be added for the final result
.SelectMany((x, i) =>
{
// digit value
var val1 = x - '0';
var res1 = new List<int>();
// to bit positions, as if it was the first digit
for (int j = 0; j < 8; j++)
{
if ((val1 & (1 << j)) != 0) res1.Add(j);
}
// to absolute bit positions, taking the digit position into account
for (int j = 1; j <= i; j++)
{
var res = new List<int>();
// multiply by 10, until actual position is reached
foreach (var item in res1)
{
res.Add(item + 1);
res.Add(item + 3);
}
// compress bits
res1 = res.Aggregate(new HashSet<int>(), (set, i1) =>
{
// two bits in the same position add up to one bit in a higher position
while (set.Contains(i1))
{
set.Remove(i1);
i1++;
}
set.Add(i1);
return set;
}).ToList();
}
return res1;
}).
// final elimination of duplicate bit indices
Aggregate(new HashSet<int>(), (set, i) =>
{
while (set.Contains(i))
{
set.Remove(i);
i++;
}
set.Add(i);
return set;
})
// transfer bit positions into a byte array - lowest bit is the last bit of the first byte
.Aggregate(new byte[(long)Math.Ceiling(input.Length / 2.0)], (res, bitpos) =>
{
res[bitpos / 8] |= (byte)(1 << (bitpos % 8));
return res;
});

建议实际上将操作拆分为单独的函数,而不是这个巨大的 linq blob ;)

关于c# - 如何在 C# 中_直接_将基数为 10(十进制)的字符串转换为字节数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35219273/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com