我最近读了相当多关于IEEE754和x87架构。我想利用南作为一个"缺失值"中的一些数字计算代码我正在和我希望使用 信号 NaN会让我抓一个浮点例外的情况下,我不想再继续的"缺失值"。 相反,我会用 安静的 南允许的"缺失值"来传播通过一个计算。然而,令南斯不工作,因为我认为他们将根据(非常有限的)文档存在于他们。

这里是一个摘要是什么我知道的(所有这些使用x87和VC++):

  • _EM_INVALID(IEEE"无效"例外)控制行为的x87时遇到Nan
  • 如果_EM_INVALID被屏蔽(唯一的例外是禁止),没有例外就是产生和操作可以返回安静,奶奶.一个运作涉及信NaN会 因为例外会引发,但将转换到安静,奶奶.
  • 如果_EM_INVALID是揭露(例外启用)、无效的操作(例如,sqrt(-1))会导致无效的例外被抛出。
  • X87 从来没有 产生令楠。
  • 如果_EM_INVALID是揭露, 任何 使用信南(即使初始化的变量,它)导致无效的例外被抛出。

标准图书馆提供了一种方式访问南值:

std::numeric_limits<double>::signaling_NaN();

std::numeric_limits<double>::quiet_NaN();

问题是,我看没有使用任何信楠。如果_EM_INVALID是掩盖它的行为完全相同的,因为安静,奶奶.由于没有南比任何其他南、没有逻辑上的差异。

如果_EM_INVALID是 屏蔽(例外启用),然后一个不能即使初始化的变量,令南:double dVal = std::numeric_limits<double>::signaling_NaN(); 因为这会引发一个例外(信令南值被载入一个x87登记册,以储存存储地址)。

你可能认为下列作为我做的:

  1. 掩_EM_INVALID.
  2. 初始化的变量与信楠。
  3. Unmask_EM_INVALID.

然而,第2步导致信南要被转换到一个安静的南,所以后使用它将 因为例外会引发!那么跆拳道?!

是否有任何工具或任何目的的一种信号楠?我明白了一个原始意图是初始化记忆,它使用一个未初始化的浮点值可能被抓到。

可以有人告诉我如果我失去了一些东西在这里?


编辑:

为了进一步说明什么我都希望做到的,这里是一个例子:

考虑进行数学运算上的矢量数据(加倍).对于一些行动,我希望允许的矢量,以包含一个"缺失值"(假装这相当于电子表格列,例如,其中的一些细胞没有价值,但它们的存在显着)。对于一些行动,我做的 要允许的矢量,以包含一个"缺失值"。 也许我想要采取不同的行动当然如果一个"缺失值"是存在的设置--也许是执行一个不同的操作(因此这不是一个无效状态)。

这种原始代码看起来像这样的东西:

const double MISSING_VALUE = 1.3579246e123;
using std::vector;

vector<double> missingAllowed(1000000, MISSING_VALUE);
vector<double> missingNotAllowed(1000000, MISSING_VALUE);

// ... populate missingAllowed and missingNotAllowed with (user) data...

for (vector<double>::iterator it = missingAllowed.begin(); it != missingAllowed.end(); ++it) {
    if (*it != MISSING_VALUE) *it = sqrt(*it); // sqrt() could be any operation
}

for (vector<double>::iterator it = missingNotAllowed.begin(); it != missingNotAllowed.end(); ++it) {
    if (*it != MISSING_VALUE) *it = sqrt(*it);
    else *it = 0;
}

注意检查"缺失值"必须执行 每一个回路迭代.虽然我理解,在大多数情况下, sqrt 功能(或者任何其他的数学作业)可能会掩盖这种检查,还有一些情况下,作为最小的(也许只是一个外),并检查是昂贵的。不要说一个事实,即"缺失值"需要一个法律输入的价值的发挥并可能导致错误,如果计算合法地到达,值(不可能的,虽然它可能是)。还是技术上是正确的,用户输入的数据,应检查对这一价值并就适当的应采取行动。我找到这个解决方案不雅和不佳的业绩。这是性能至关重要的代码,我们绝对没有奢侈品的平行结构的数据或数据元对象的某种。

南版本是这样的:

using std::vector;

vector<double> missingAllowed(1000000, std::numeric_limits<double>::quiet_NaN());
vector<double> missingNotAllowed(1000000, std::numeric_limits<double>::signaling_NaN());

// ... populate missingAllowed and missingNotAllowed with (user) data...

for (vector<double>::iterator it = missingAllowed.begin(); it != missingAllowed.end(); ++it) {
    *it = sqrt(*it); // if *it == QNaN then sqrt(*it) == QNaN
}

for (vector<double>::iterator it = missingNotAllowed.begin(); it != missingNotAllowed.end(); ++it) {
    try {
        *it = sqrt(*it);
    } catch (FPInvalidException&) { // assuming _seh_translator set up
        *it = 0;
    }
}

现在的明确的检查是消除和表现应加以改进。我认为这将所有工作,如果我可以初始化的矢量不碰FPU寄存器...

此外,我想任何有自尊的 sqrt 执行检查南和返回南。

有帮助吗?

解决方案

我的理解是,目的的信南是初始化数据结构,但是,当然 运行 初始化时在C运行的风险具有南载入浮动登记册的一部分初始化,从而触发的信号,因为编译器不知道这浮动价值需要复制使用的整登记册。

我希望你可以初始化 static 值与信南,但即使这样,将需要一些特殊处理由编译器,避免它具有转变为一个安静的楠。你也许可以用一点点的铸造的魔法,以避免它视为一个浮动价值,在初始化。

如果你写在小型矿场,这将不是一个问题。但是,在C和特别是用C++,我想你会有颠复类型的系统的以初始化的变量楠。我建议使用 memcpy.

其他提示

使用特别值(即使NULL)可以让你的数据很多muddier和你的代码很混乱.这将是不可能的区别之间的QNaN结果和QNaN"特别"的价值。

你可能会更好保持一个平行的数据结构,以跟踪有效性,或者也许有你FP数据以不同(稀少)的数据结构只保留有效数据。

这是相当一般性意见;特别值非常有用,在某些情况下(例如真的很紧张存储器或履约束),但是作为背景下的增长较大,他们可能会导致更多的困难,比他们的价值。

你就不能有一个const uint64_t那里的位已被设置为一个令楠?只要你把它作为一个整数类型,令南并不是从其他不同的整数。你可以写信它,你想要通过的指针铸:

Const uint64_t sNan = 0xfff0000000000000;
Double[] myData;
...
Uint64* copier = (uint64_t*) &myData[index];
*copier=sNan | myErrorFlags;

信息位设置:https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top