这个 C++ 会吗?将 PDP-11 浮点数转换为 IEEE?
我正在维护一个程序,该程序从 PDP-11(模拟!)程序中获取数据并将其放入基于 Windows 的现代系统中。我们遇到一些数据值报告为“1.#QNAN”和“1.#QNB”的问题。客户最近透露,PDP-11 程序中的“坏”值由 2 个 16 位字表示,其中除第一个位外的所有位均已设置。我认为正是当我们尝试将它们转换为 IEEE 浮点数时,我们才会遇到错误。
我发现下面的代码用于将 PDP-11 值转换为 IEEE。我不太了解浮点表示的复杂性,但这对我来说似乎有点简单!这真的能可靠地将 PDP-11 浮点数转换为 IEEE 吗?
// ---------------------------------------------------------------- cnvPDPfloat
// CNVPDPFLOAT
// ----------------------------------------------------------------------------
//
// Converts PDP11 float (two 16-bit words) into IEEE float
//
// PDP11 and IEEE floats have same layout so can be mapped onto eachother.
// But PDP11 exponent must have 2 subtracted for IEEE. Or just divide by 4.
//
float cnvPDPfloat( PDP11Float input )
{
union
{
unsigned long pdp11;
float ieee;
} uFloat;
uFloat.pdp11 = (input.word[0] << 16) + input.word[1];
return (uFloat.ieee / (float) 4.0);
}
——阿利斯泰尔。
I am maintaining a program that takes data from a PDP-11 (emulated!) program and puts it into a modern Windows-based system. We are having problems with some of the data values being reported as "1.#QNAN" and also "1.#QNB". The customer has recently revealed that 'bad' values in the PDP-11 program are represented by 2 16-bit words with all the bits set except the first. I think that it is when we try to convert these to IEEE floats that we are getting the errors.
I have found the code below that is used for converting the PDP-11 values to IEEE. I am not very in touch with the intricacies of floating point representations but this seems a bit simple to me! Would this really reliably convert PDP-11 floats to IEEE?
// ---------------------------------------------------------------- cnvPDPfloat
// CNVPDPFLOAT
// ----------------------------------------------------------------------------
//
// Converts PDP11 float (two 16-bit words) into IEEE float
//
// PDP11 and IEEE floats have same layout so can be mapped onto eachother.
// But PDP11 exponent must have 2 subtracted for IEEE. Or just divide by 4.
//
float cnvPDPfloat( PDP11Float input )
{
union
{
unsigned long pdp11;
float ieee;
} uFloat;
uFloat.pdp11 = (input.word[0] << 16) + input.word[1];
return (uFloat.ieee / (float) 4.0);
}
--- Alistair.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
该代码不会检查未定义值、干净零和脏零,但除以4(在其他答案中讨论)是好的。 OP 可能知道这一点,因为他们会发现结果是否总是错误的。
今天指数偏差也让我感到困惑,所以我将引用我刚刚在这份精美文档中读到的内容: 带有隐藏位的二进制浮点数:
这也解释了为什么一些参考文献指出 IEEE 偏差为 126。
The code doesn't check for undefined value, clean-zero and dirty-zero, but dividing by 4, discussed in other answers, is good. The OP probably knows it because they would spot if the result was always wrong.
The exponent bias also confused me today, so I'll quote what I've just read in this fine document: Binary floats with hidden bit:
This also explains why some references state that IEEE bias is 126.
在此页面中,PDP-11 格式与IEEE-754 浮点格式,不同之处在于 PDP-11 中指数偏置 128,而 IEEE-754 中指数偏置 127。因此,您需要除以 2.0,而不是 4.0。这不考虑 NaN 和无穷大,但从我的谷歌搜索来看,看起来 PDP-11 没有这些。
您还会遇到溢出问题。 PDP 格式较早溢出,但我假设这没关系,因为一旦数字已经溢出,您就无法真正执行任何操作。
From this page, the PDP-11 format is identical to IEEE-754 floating-point format except that the exponent is biased by 128 in PDP-11, whereas it is biased by 127 in IEEE-754. So, you need to divide by 2.0 and not 4.0. This doesn't take care of NaNs and infinities, but from my google searches, looks like PDP-11 didn't have those.
You will also have issues with overflow. The PDP format overflows earlier, but I am assuming that is OK since you can't really do anything once a number has already overflown.
PDP-11 使用混合字节序表示浮点数。 这部分代码
因此,如果您的数据在获取之前尚未进行字交换,则
是正确的。本文档提供了许多不同浮点格式表示的详细信息 http://www.quadibloc .com/comp/cp0201.htm
它说 t PDP-11/VAX 使用了超过 128 的指数表示法。而 IEEE 754 使用多余的 126 表示法,因此如果正确的话,除以 4 似乎是调整指数的正确方法。
但是,维基百科表示 IEEE 754 的指数偏差是 127,而不是 126。因此,上述文档要么使用了奇怪的符号,要么是不正确的。您可能需要除以 2 而不是除以 4。
The PDP-11 used a mixed-endian representation for floating point numbers. so this part of the code
is correct if your data hasn't already been word-swapped before you get it.
This document gives details of the representation for a lot of different floating point formats http://www.quadibloc.com/comp/cp0201.htm
It says that t PDP-11/VAX used excess 128 notation for the exponent. whereas IEEE 754 uses excess 126 notation, so if it is correct, dividing by 4 seems to be the correct way to adjust the exponent.
However, Wikipedia says that the exponent bias for IEEE 754 is 127, not 126. So either the above document is using a strange notation, or it is incorrect. It's possible that you need to divide by 2 rather than by 4.
除了 NaN 和 Inf 之外,您还可能会遇到非正规值转换的问题。我不知道 PDP-11 是否支持这些,但 IEEE 754 规定,当指数字段为 0 时,数字是非正规的,这实际上意味着尾数字段中隐含的前导 1 变为 0。这样就有了当数字减少时逐渐收敛到0。
@John - IEEE 754 标准规定指数偏差是 127,而不是 126。Wiki 是正确的,其他参考是错误的。因此,该比率将为 2.0。
In addition to NaN and Inf, you may also have problems with conversion of denormal values. I don't know if PDP-11 supports these, but IEEE 754 states that when the exponent field is 0, then the numbers are denormals, effectively meaning that the implied leading 1 in the mantissa field becomes a 0. This way there is a gradual convergence to 0 when numbers are decreasing.
@John - The IEEE 754 standard states that the exponent bias is 127, not 126. Wiki is right and the other reference is wrong. So, the ratio would be 2.0.