简体   繁体   English

向字符串流输入浮点数时的“浮点无效运算”

[英]“Floating-point invalid operation” when inputting float to a stringstream

I have a simple piece of code that extracts a float from a FORTRAN-generated REAL array, and then inserts it into a stream for logging. 我有一段简单的代码,它从FORTRAN生成的REAL数组中提取一个浮点数,然后将其插入流中进行记录。 Although this works for the first 30 cases, on the 31st it crashes with a "Floating-point invalid operation". 尽管此方法适用于前30种情况,但在31日因“浮点无效操作”而崩溃。

The code is: 代码是:

int FunctionDeclaration(float* mrSwap)
{
...
float swap_float;
stringstream message_stream;
...
swap_float = *(mrSwap+30-1);
...
message_stream.clear();
message_stream <<  30 << "\t" << swap_float << "\tblah blah blah \t";

When debugging, the value of swap_float the instance before the crash (on the last line, above) is 1711696.3 - other than this being much larger than most of the values up until this point, there is nothing particularly special about it. 调试时,崩溃之前实例的swap_float的值(在上面的最后一行)为1711696.3-除此之外,此值比到目前为止的大多数值都大得多,没有什么特别的。

I have also tried replacing message_stream with cerr, and got the same problem. 我也尝试过用cerr替换message_stream,并遇到同样的问题。 I had hitherto believed cerr to be pretty much indestructable - how can a simple float destroy it? 迄今为止,我一直相信cerr几乎是坚不可摧的-简单的浮子如何将其摧毁?

Edit: 编辑:

Thanks for the comments: I've added the declaration of mrSwap. 感谢您的评论:我已经添加了mrSwap的声明。 mrSwap is approximately 200 long, so I'm a long way off the end. mrSwap大约有200长,因此距离目标还有很长的路要走。 It is populated outside of my control, and individual entries may not be populated - but to the best of my understanding, this would just mean that swap_float would be set to a random float? 它是在我的控制范围之外填充的, 可能不会填充单个条目-但据我所知,这仅意味着将swap_float设置为随机浮点数?

individual entries may not be populated - but to the best of my understanding, this would just mean that swap_float would be set to a random float? 可能不会填充单个条目-但据我所知,这仅意味着swap_float将设置为随机浮点数?

Emphatically not. 重点不是。 Certain bit patterns in an IEEE floating-point number indicate an invalid number -- for instance, the result of an overflowing arithmetic operation, or an invalid one (such as 0.0/0.0). IEEE浮点数中的某些位模式表示一个无效数-例如,算术运算溢出的结果或一个无效数(例如0.0 / 0.0)。 The puzzling thing here is that the debugger apparently accepts the number as valid, while cout doesn't. 令人费解的是,调试器显然将数字视为有效,而cout则不接受。

Try getting the bit layout of swap_float . 尝试获取swap_float的位布局。 On a 32-bit system: 在32位系统上:

int i = *(int*)&swap_float;

Then print i in hexadecimal, and let us know what you see. 然后以十六进制打印i ,并告诉我们您所看到的内容。

Updated to add: From Mike's comment, i=1238430338, which is 49D0F282 in hex. 更新后添加:从Mike的注释中,i = 1238430338,十六进制为49D0F282。 This is a valid floating-point number, equal to exactly 1711696.25. 这是一个有效的浮点数,精确等于1711696.25。 So I don't know what's going on, I'm afraid. 恐怕我不知道发生了什么。 The only thing I can suggest is that maybe the compiler is loading the invalid floating-point number directly from the mrSwap array into the floating-point register bank, without going through swapFloat . 我唯一可以建议的是,也许编译器正在将无效的浮点数直接从mrSwap数组mrSwap到浮点寄存器组中,而无需通过swapFloat So the true value of swapFloat is simply not available to the debugger. 因此, swapFloat的真实值根本无法用于调试器。 To check this, try 要检查此,请尝试

int j = *(int*)(mrSwap+30-1);

and tell us what you see. 告诉我们您所看到的。

Updated again to add: Another possibility is a delayed floating-point trap. 再次更新以添加:另一种可能性是延迟浮点陷阱。 The floating-point co-processor (built into the CPU these days) generates a floating-point interrupt because of some illegal operation, but the interrupt doesn't get noticed until the next floating-point operation is attempted. 由于某些非法操作,浮点协处理器(如今已内置在CPU中)会生成浮点中断,但是直到尝试下一次浮点操作时,该中断才会被注意到。 So this crash might be a result of the previous floating-point operation, which could be anywhere. 因此,此崩溃可能是由于先前的浮点操作(可能在任何地方)导致的。 Good luck with that... 祝你好运...

I'm just adding this answer to highlight the correct solution within TonyK's answer above - because we did a few loops, the answer has been edited, and because several salient points are within the comments, the actual answer may not be immediately apparent. 我只是添加此答案以突出上述TonyK答案中的正确解决方案-因为我们做了几次循环,答案已被编辑,并且由于注释中有几个要点,所以实际答案可能不会立即显现。 All credit should go to TonyK for the solution. 该解决方案应归功于TonyK。

"Another possibility is a delayed floating-point trap. The floating-point co-processor (built into the CPU these days) generates a floating-point interrupt because of some illegal operation, but the interrupt doesn't get noticed until the next floating-point operation is attempted. So this crash might be a result of the previous floating-point operation, which could be anywhere." “另一种可能是延迟的浮点陷阱。由于某些非法操作,浮点协处理器(如今已内置在CPU中)会产生浮点中断,但是直到下一次浮点时该中断才被注意到尝试执行点操作。因此,此崩溃可能是由于先前的浮点操作(可能在任何地方)导致的。” - TonyK -托尼

This was indeed the problem: in my comparison using IsSame, the other value was NaN (this is a valid value in this context), and although it happily subtracted it from swap_float, it put a flag in saying to report the next operation as an error. 这确实是问题所在:在我使用IsSame进行比较的过程中,另一个值是NaN(在这种情况下,这是一个有效值),尽管它很高兴地从swap_float中减去了它,但它还是说了一个标志,表示将下一个操作报告为错误。 I have to say that I was completely unaware that that was possible - I thought that if it worked, it worked. 我必须说,我完全不知道这是可能的-我认为如果可行,它就会奏效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM