- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当用 Delphi 2009 编译并运行时,这个控制台应用程序会写“奇怪”。“小于”运算符两侧的值相等,但代码的行为就像它们不相等一样。我该怎么做才能避免这个问题?
program Project5;
{$APPTYPE CONSOLE}
var
C: Currency;
begin
C := 1.32;
if C < 1.32 then
begin
WriteLn('strange');
end;
ReadLn;
end.
附:代码与其他值一起工作正常。
这个answer Barry Kelly 解释说,货币类型“不像浮点代码那样容易受到精度问题的影响。”
最佳答案
这似乎是 Delphi 中的回归。
Delphi 2010 中的输出是“奇怪的”。但在 XE2 中没有输出,因此不存在该错误。我手头没有 XE 可供测试,但感谢 @Sertac 确认 XE 也输出“奇怪”。请注意,旧版本的 Delphi 也可以,因此这是 D2009 左右时间的回归。
2010 年生成的代码是:
Project106.dpr.10: if C < 1.32 then
004050D6 DB2D18514000 fld tbyte ptr [$00405118]
004050DC DF2D789B4000 fild qword ptr [$00409b78]
004050E2 DED9 fcompp
004050E4 9B wait
004050E5 DFE0 fstsw ax
004050E7 9E sahf
004050E8 7319 jnb $00405103
Project106.dpr.12: WriteLn('strange');
文字 1.32 存储为 10 字节浮点值,其值为 13200。这是一个可精确表示的二进制浮点值。 13200 存储为 10 字节 float 的位模式为:
00 00 00 00 00 00 40 CE 0C 40
However, the bit pattern stored in the literal at $00405118 is different, and is slightly greater than 13200
. The value is:
01 00 00 00 00 00 40 CE 0C 40
And that explains why C < 1.32
evaluates to True
.
On XE2 the code generated is:
Project106.dpr.10: if C < 1.32 then
004060E6 DF2DA0AB4000 fild qword ptr [$0040aba0]
004060EC D81D28614000 fcomp dword ptr [$00406128]
004060F2 9B wait
004060F3 DFE0 fstsw ax
004060F5 9E sahf
004060F6 7319 jnb $00406111
Project106.dpr.12: WriteLn('strange');
请注意,文字保存在 4 字节 float 中。通过与 dword ptr [$00406128]
进行比较就可以看出这一点。 。如果我们查看存储在 $00406128
的单精度 float 的内容我们发现:
00 40 4E 46
And that is exactly 13200 as represented as a 4 byte float.
My guess is that the compiler in 2010 does the following when faced with 1.32
:
$00405118
.Because 1.32 is not exactly representable, it turns out that the final 10 byte float is not exactly 13200. And presumably the regression came about when the compiler switch from storing these literals in 4 byte floats to storing them in 10 byte floats.
The fundamental problem is that Delphi's support for the Currency
data type is founded on an utterly flawed design. Using binary floating point arithmetic to implement a decimal fixed point data type is simply asking for trouble. The only sane way to fix the design would be to completely re-engineer the compiler to use fixed point integer arithmetic. It's rather disappointing to note that the new 64 bit compiler uses the same design as the 32 bit compiler.
To be quite honest with you, I would stop the Delphi compiler doing any floating point work with Currency
literals. It's just a complete minefield. I would do the 10,000 shift in my head like this:
function ShiftedInt64ToCurrency(Value: Int64): Currency;
begin
PInt64(@Result)^ := Value;
end;
然后调用代码将是:
C := 1.32;
if C < ShiftedInt64ToCurrency(13200) then
Writeln ('strange');
编译器没有办法把它搞砸!
哼!
关于delphi - 货币值(value)/恒定值比较的奇怪结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14358407/
我有这种来自 Google map 自动完成的奇怪行为(或者我可能错过了某事)...想法?奇怪的: 您在输入中输入某物,例如“伦敦” 您按 [ENTER] 你按下 [CLEAR] 按钮 你点击进入'输
这段代码与《Learning Java》(Oracle Press Books)一书中的代码完全一样,但它不起作用。我不明白为什么它不起作用,它应该起作用。我用 OpenJDK 和 Sun JDK 7
示例 1 中究竟发生了什么?这是如何解析的? # doesnt split on , [String]::Join(",",("aaaaa,aaaaa,aaaaa,aaaaa,aaaaa,aa
我需要获得方程式系统的解决方案。为此,我使用函数sgesv_()。 一切都很好,它使我感到解决方案的正确结果。 但是我得到一个奇怪的警告。 警告:从不兼容的指针类型传递'sgesv_'的参数3 我正在
我目前在制作动画时遇到一个奇怪的问题: [UIView animateWithDuration:3 delay:0
alert('works'); $(window).load(function () { alert('does not work'); });
我的代码: public class MyTest { public class StringSorter implements Comparator { public
我正在学习 JavaScript。尝试理解代码, function foo (){ var a = b = {name: 'Hai'}; document.write(a.name +''
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
这按预期工作: [dgorur@ted ~]$ env -i env [dgorur@ted ~]$ 这样做: [dgorur@ted ~]$ env -i which date which: no
struct BLA { int size_; int size()const{ return size_; } } int x; BLA b[ 2 ]; BLA * p = &b[
我有以下代码: #test img {vertical-align: middle;} div#test { border: 1px solid green; height: 150px; li
我想大多数使用过 C/C++ 的人都对预处理器的工作原理有一定的直觉(或多或少)。直到今天我也是这么认为的,但事实证明我的直觉是错误的。故事是这样的: 今天我尝试了一些东西,但我无法解释结果。首先考虑
我想为 TnSettings 做 mock,是的,如果通过以下方法编写代码,它就可以工作,问题是我们需要为每个案例编写 mock 代码,如果我们只 mock 一次然后执行多个案例,那么第二个将报告异常
我的项目中有以下两个结构 typedef volatile struct { unsigned char rx_buf[MAX_UART_BUF]; //Input buffer over U
Regex rx = new Regex(@"[+-]"); string[] substrings = rx.Split(expression); expression = "-9a3dcb
我的两个应用程序遇到了一个奇怪的问题。这是设置: 两个 tomcat/java 应用程序,在同一个网络中运行,连接到相同的 MS-SQL-Server。一个应用程序,恰好按顺序位于 DMZ 中可从互联
我目前正在与 Android Api Lvl 8 上的 OnLongClickListener 作斗争。 拿这段代码: this.webView.setOnLongClickListener(new
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
只是遇到了奇怪的事情。我有以下代码: -(void)ImageDownloadCompleat { [self performSelectorOnMainThread:@selector(up
我是一名优秀的程序员,十分优秀!