Double Exp(double)出乎意料地返回NAN(无浮子溢出)

double exp(double) unexpectedly returns NaN (no float overflow)

本文关键字:溢出 NAN Exp double 出乎意料 Double 返回      更新时间:2023-10-16

我一直在努力根据普朗克定律实施黑体辐射,但以下内容:

double BlackBody(double T, double wavelength) {
  wavelength /= 1e9; // pre-scale wavelength to meters
  static const double h = 6.62606957e-34; // Planck constant
  static const double c = 299792458.0; // speed of light in vacuum
  static const double k = 1.3806488e-23; // Boltzmann constant
  double exparg = h*c / (k*wavelength*T);
  double exppart = std::exp(exparg) - 1.0;
  double constpart = (2.0*h*c*c);
  double powpart = pow(wavelength, -5.0);
  double v = constpart * powpart / exppart;
  return v;
}

i有一个浮点[max-min 1]阵列,其中static const int max = 780,static state int int min = 380。=阵列索引 最小)。Intermentyspectrum :: Blackbody执行此迭代,而Min和Max均为静态成员Vars,并且数组也在Intermenty Spectrum中。

IntensitySpectrum spectrum;
Vec3 rgb = spectrum.ToRGB();
rgb /= std::max(rgb.x, std::max(rgb.y, rgb.z));
for (int xc = 0; xc < grapher.GetWidth(); xc++) {
  if (xc % 10 == 0) {
    spectrum.BlackBody(200.f + xc * 200.f);
    spectrum.Scale(1.0f / 1e+14f);
    rgb = spectrum.ToRGB();
    rgb /= std::max(rgb.x, std::max(rgb.y, rgb.z));
  }
  for (int yc = 20; yc < 40; yc++) {
    grapher(xc, yc) = grapher.FloatToUint(rgb.x, rgb.y, rgb.z);
  }
}

问题是,线频谱。BlackBody()将数组的0元素设置为NAN,仅设置为0。此外,第一次迭代也不会发生,但是所有以下所有迭代都不会发生xc> = 10。

来自VS调试器的文本:spectrum = {intense = 0x009bec50 {-1。#ind0000,520718784。,537559104.,554832896.,572547904.,590712128.

我跟踪了错误,:: blackbody()函数中的exppart变为nan,尽管它的参数接近2.0,但基本上是exp()返回nan,因此绝对不会溢出。但仅适用于数组索引0。它神奇地开始为其余400个索引工作。

我知道内存超支可能会导致这样的事情。这就是为什么我仔细检查记忆处理的原因。我正在从另一个更大的自制库中链接vec3,并且可能包含错误,但是我从vec3中使用的内容与内存无关。

几个小时后,我完全毫无头绪。还有什么可能导致这个?优化器还是Winapi欺骗了我...?(UHM,是的,该程序使用Winapi创建一个窗口,并使用几乎空的WNDProc,在WM_PAINT上调用我的代码。)

感谢您提前的帮助。

很抱歉使其不清楚。这是布局:

// member
class IntensitySpectrum {
public:
    void BlackBody(float temperature) {
        // ...
        this->intensity[i] = ::BlackBody(temperature, wavelength(i));
        // ...
    }
private:
    static const int min = 380;
    static const int max = 780;
    float intensity[max-min+1];
}
// global
double BlackBody(double T, double wavelength);

如果您碰巧使用了MSVC 2013,则可能的解释是,您在某个地方试图将float Infinity转换为int的地方。MSVC 2013中的一个错误在发生这种情况时会引起X87 FPU堆栈的不平衡推动。触发该错误8次,而您的FPU堆栈完全已满,并且随后的任何推动值(例如调用'exp())的尝试将导致"无效操作"并返回不确定(例如1.#1 Ind)。请注意,即使您使用SSE2浮点指令进行编译,此错误仍然可以咬合,因为调用惯例决定了浮点返回值在FPU堆栈的顶部返回。

要检查这是否是您的问题,请在对" Exp()"的错误呼叫之前查看您的FPU寄存器。如果您的标签寄存器全部为零,则您的FPU堆栈已满。

  • http://connect.microsoft.com/visualstudio/feedback/details/806362/vc12-pollutes-the-pollutes-the-floating-point-point-point-stack-when-casting-when-casting-infinity-infinity-infinity-infinity-infinity-infinity-nan-to-nan-to-nan-to-nan-to-nan to-nan to-ni to-ni li>

MS声称这将在MSVC 2013的更新2中修复。

以下函数调用只有1个参数:

spectrum.BlackBody(200.f + xc * 200.f);

因此,它不能调用您定义为

的函数
double BlackBody(double T, double wavelength)

如果您查看::BlackBody实现,我敢打赌,您在某处有0个错误。