C ++,Java在语言的语法中都包含[ - ] 0xh.hhhhp +/- d格式,其他语言如python和C99都支持解析这些字符串(float.fromhex,scanf)。
我还没有找到一种方法在C#中解析这个精确的十六进制编码指数格式或使用.NET库。
有没有一种很好的方法来处理这个问题,或者是一个不错的替代编码? (十进制编码不准确)。
示例字符串: 0x1p-8 -0xfe8p-12
谢谢
答案 0 :(得分:2)
不幸的是,我不知道.NET内置的任何方法与Python的float.fromhex()相比。所以我想你唯一能做的就是在C#中使用自己的.fromhex()。这项任务的难度范围从“有些容易”到“非常困难”,具体取决于您对解决方案的完整程度和优化程度。
正式地,IEEE 754规范允许十六进制系数内的小数(即0xf.e8p-12),这为我们增加了一层复杂性(因为我很沮丧).NET也不支持Double 。十六进制字符串的.Parse()。
如果您可以将问题约束到您提供的只有整数作为系数的示例,则可以使用以下解决方案使用字符串操作:
public static double Parsed(string hexVal)
{
int index = 0;
int sign = 1;
double exponent = 0d;
//Check sign
if (hexVal[index] == '-')
{
sign = -1;
index++;
}
else if (hexVal[index] == '+')
index++;
//consume 0x
if (hexVal[index] == '0')
{
if (hexVal[index+1] == 'x' || hexVal[index+1] == 'X')
index += 2;
}
int coeff_start = index;
int coeff_end = hexVal.Length - coeff_start;
//Check for exponent
int p_index = hexVal.IndexOfAny(new char[] { 'p', 'P' });
if (p_index == 0)
throw new FormatException("No Coefficient");
else if (p_index > -1)
{
coeff_end = p_index - index;
int exp_start = p_index + 1;
int exp_end = hexVal.Length;
exponent = Convert.ToDouble(hexVal.Substring(exp_start, exp_end - (exp_start)));
}
var coeff = (double)(Int32.Parse(hexVal.Substring(coeff_start, coeff_end), NumberStyles.AllowHexSpecifier));
var result = sign * (coeff * Math.Pow(2, exponent));
return result;
}
如果您正在寻找与Python的fromhex()相同的功能,您可以尝试将CPython implementation转换为C#(如果您愿意)。我试过了,但由于我对标准不是很熟悉而无法完成他们正在寻找的所有溢出检查,因此无法理解。它们还允许其他内容,例如无限制的前导和尾随空格,我的解决方案不允许这样做。
我的解决方案是“一些简单”的解决方案。我猜你是否真的知道你的东西,你可以在比特级别建立符号,指数和尾数,而不是将所有东西都加倍。你绝对可以在一次传递中完成它,而不是使用.Substring()方法作弊。
希望这至少能让你走上正轨。
答案 1 :(得分:1)
我编写了C#代码,用于格式化和解析IEEE 754r中描述的并由C99,C ++ 11和Java支持的十六进制浮点格式的数字。该代码是F#的BSD许可FParsec库的一部分,并包含在一个文件中: https://bitbucket.org/fparsec/main/src/tip/FParsecCS/HexFloat.cs
支持的格式在http://www.quanttec.com/fparsec/reference/charparsers.html#members.floatToHexString
处有所描述可以在https://bitbucket.org/fparsec/main/src/tip/Test/HexFloatTests.fs
找到测试代码(用F#编写)