- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当我尝试Trunc()
一个Real
值时,出现一个(可重复的)浮点异常。
例如。:
Trunc(1470724508.0318);
ns: Real;
v: Int64;
ns := ((HighPerformanceTickCount*1.0)/g_HighResolutionTimerFrequency) * 1000000000;
v := Trunc(ns);
Trunc(ARealValue);
fld qword ptr [ebp-$10]
ST0
中。
0018E9D0: 6702098C 41D5EA5E (as DWords)
0018E9D0: 41D5EA5E6702098C (as QWords)
0018E9D0: 1470724508.0318 (as Doubles)
call @TRUNC
sub esp,$0c
wait
fstcw word ptr [esp] //Store Floating-Point Control Word on the stack
wait
fldcw word ptr [cwChop] //Load Floating-Point Control Word
fistp qword ptr [esp+$04] //Converts value in ST0 to signed integer
//stores the result in the destination operand
//and pops the stack (increments the stack pointer)
wait
fldcw word ptr [esp] //Load Floating-Point Control Word
pop ecx
pop eax
pop edx
ret
const cwChop : Word = $1F32;
procedure _TRUNC;
asm
{ -> FST(0) Extended argument }
{ <- EDX:EAX Result }
SUB ESP,12
FSTCW [ESP] //Store foating-control word in ESP
FWAIT
FLDCW cwChop //Load new control word $1F32
FISTP qword ptr [ESP+4] //Convert ST0 to int, store in ESP+4, and pop the stack
FWAIT
FLDCW [ESP] //restore the FPCW
POP ECX
POP EAX
POP EDX
end;
fistp qword ptr [esp+$04]
fistp
指令时与在
fld
指令后相同。
sub esp,$0c
:我看着它将堆栈压低了12个字节
fstcw word ptr [esp]
:我看到它将$ 027F推入当前堆栈指针
fldcw word ptr [cwChop]
:我看着浮点控制标志改变
fistp qword ptr [esp+$04]
:它将把Int64写入它在堆栈中创建的房间
$41D5EA5E6702098C
,我试图进行设置:
var
ns: Real;
nsOverlay: Int64 absolute ns;
v: Int64;
begin
nsOverlay := $41d62866a2f270dc;
v := Trunc(ns);
end;
mov [ebp-$08],$a2f270dc
mov [ebp-$04],$41d62866
fld qword ptr [ebp-$08]
call @TRUNC
call
到
@trunc
的点,浮点寄存器ST0包含一个值:
invalid floating point exception
的情况是什么?
cwChop
加载控制字之前的值是什么?
cwChop
的值看起来在负载控制字
$1F32
之前是正确的。但是加载后,实际的控制字是错误的:
function PerformanceTicksToNs(const HighPerformanceTickCount: Int64): Int64;
//Convert high-performance ticks into nanoseconds
var
ns: Real;
v: Int64;
begin
Result := 0;
if HighPerformanceTickCount = 0 then
Exit;
if g_HighResolutionTimerFrequency = 0 then
Exit;
ns := ((HighPerformanceTickCount*1.0)/g_HighResolutionTimerFrequency) * 1000000000;
v := Trunc(ns);
Result := v;
end;
var
i1, i2: Int64;
ns: Real;
v: Int64;
vOver: Int64 absolute ns;
begin
i1 := 5060170;
i2 := 3429541;
ns := ((i1*1.0)/i2) * 1000000000;
//vOver := $41d62866a2f270dc;
v := Trunc(ns);
$1332
:
$1332 = 0001 00 11 00 110010
0 ;Don't allow invalid numbers
1 ;Allow denormals (very small numbers)
0 ;Don't allow divide by zero
0 ;Don't allow overflow
1 ;Allow underflow
1 ;Allow inexact precision
0 ;reserved exception mask
0 ;reserved
11 ;Precision Control - 11B (Double Extended Precision - 64 bits)
00 ;Rounding control -
0 ;Infinity control - 0 (not used)
$027F
$027F = 0000 00 10 01 111111
1 ;Allow invalid numbers
1 ;Allow denormals (very small numbers)
1 ;Allow divide by zero
1 ;Allow overflow
1 ;Allow underflow
1 ;Allow inexact precision
1 ;reserved exception mask
0 ;reserved
10 ;Precision Control - 10B (double precision)
00 ;Rounding control
0 ;Infinity control - 0 (not used)
crChop
控制字:
$1F32
$1F32 = 0001 11 11 00 110010
0 ;Don't allow invalid numbers
1 ;Allow denormals (very small numbers)
0 ;Don't allow divide by zero
0 ;Don't allow overflow
1 ;Allow underflow
1 ;Allow inexact precision
0 ;reserved exception mask
0 ;unused
11 ;Precision Control - 11B (Double Extended Precision - 64 bits)
11 ;Rounding Control
1 ;Infinity control - 1 (not used)
000 ;unused
CTRL
后的
$1F32
标志:
$1F72
$1F72 = 0001 11 11 01 110010
0 ;Don't allow invalid numbers
1 ;Allow denormals (very small numbers)
0 ;Don't allow divide by zero
0 ;Don't allow overflow
1 ;Allow underflow
1 ;Allow inexact precision
1 ;reserved exception mask
0 ;unused
11 ;Precision Control - 11B (Double Extended Precision - 64 bits)
11 ;Rounding control
1 ;Infinity control - 1 (not used)
00011 ;unused
Win32Check
或
RaiseLastWin32Error
,我们想要一个
RaiseLastFPError
。我能想到的最好的是:
procedure RaiseLastFPError();
var
statWord: Word;
const
ERROR_InvalidOperation = $01;
// ERROR_Denormalized = $02;
ERROR_ZeroDivide = $04;
ERROR_Overflow = $08;
// ERROR_Underflow = $10;
// ERROR_InexactResult = $20;
begin
{
Excellent reference of all the floating point instructions.
(Intel's architecture manuals have no organization whatsoever)
http://www.plantation-productions.com/Webster/www.artofasm.com/Linux/HTML/RealArithmetica2.html
Bits 0:5 are exception flags (Mask = $2F)
0: Invalid Operation
1: Denormalized - CPU handles correctly without a problem. Do not throw
2: Zero Divide
3: Overflow
4: Underflow - CPU handles as you'd expect. Do not throw.
5: Precision - Extraordinarily common. CPU does what you'd want. Do not throw
}
asm
fwait //Wait for pending operations
FSTSW statWord //Store floating point flags in AX.
//Waits for pending operations. (Use FNSTSW AX to not wait.)
fclex //clear all exception bits the stack fault bit,
//and the busy flag in the FPU status register
end;
if (statWord and $0D) <> 0 then
begin
//if (statWord and ERROR_InexactResult) <> 0 then raise EInexactResult.Create(SInexactResult)
//else if (statWord and ERROR_Underflow) <> 0 then raise EUnderflow.Create(SUnderflow)}
if (statWord and ERROR_Overflow) <> 0 then raise EOverflow.Create(SOverflow)
else if (statWord and ERROR_ZeroDivide) <> 0 then raise EZeroDivide.Create(SZeroDivide)
//else if (statWord and ERROR_Denormalized) <> 0 then raise EUnderflow.Create(SUnderflow)
else if (statWord and ERROR_InvalidOperation) <> 0 then raise EInvalidOp.Create(SInvalidOp);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
d: Real;
dover: Int64 absolute d;
begin
d := 1.35715152325557E020;
// dOver := $441d6db44ff62b68; //1.35715152325557E020
d := Round(d); //<--floating point exception
Self.Caption := FloatToStr(d);
end;
ST0
寄存器包含有效的浮点值。浮点控制字是
$1372
。浮点异常标志全部清除:
IE
(无效操作)标志
ES
(Exception)标志
Round()
。
最佳答案
该问题发生在其他地方。当您的代码输入Trunc
时,控制字将设置为$027F
,即IIRC,即默认的Windows控制字。这掩盖了所有例外。这是一个问题,因为Delphi的RTL期望对异常进行屏蔽。
并查看FPU窗口,确定有错误。 IE和PE标志都已设置。最重要的是IE。这意味着在代码序列的前面,存在被屏蔽的无效操作。
然后,调用Trunc
修改控制字以取消屏蔽异常。查看第二个FPU窗口截图。 IE为1但IM为0。所以繁荣,引发了更早的异常,您被认为是Trunc
的错误。不是。
您需要追溯调用堆栈,以找出为什么控制字不是Delphi程序中应有的字。应该是$1332
。您很可能正在调用某个第三方库,该库会修改控制字而不还原它。您必须找到罪魁祸首,并在对该函数的任何调用返回时负责。
将控制字放回原位后,您将找到导致此异常的真正原因。显然有非法的FP操作。一旦控制字消除了异常,将在正确的位置引发错误。
请注意,不必担心$1372
和$1332
或$1F72
和$1F32
之间的差异。与CTRL
控制字相比,这是一个奇怪的事情,其中有些字节是保留的,无视您的劝告以清除它们。
关于delphi - 无效的浮点运算调用Trunc(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22210233/
使用方法 TRUNC SQL Server 2012 中的函数,因为我收到错误: 'TRUNC' is not a recognized built-in function name.' 当我执行语句
看下面的代码,为什么Trunc函数的结果不一样? procedure TForm1.Button1Click(Sender: TObject); var D: Double; E: Exten
我想在javascript中 chop 一个数字,即去掉小数部分: chop (2.6)==2 trunc (-2.6) == -2 经过大量基准测试后,我的答案是: function trunc
下面的代码在 Chrome 中运行良好,但在 IE 浏览器中我看到以下控制台错误: object does not support property or method 'trunc' 代码: var
java.lang.Math 类有 ceil()、floor()、round() 方法,但没有 trunc() 方法。 同时,我在实践中看到 .intValue() 方法(实际上执行 (int) 转换
tl;dr: double b=a-(size_t)(a) 比 double b=a-trunc(a) 快 我正在为图像实现旋转功能,我注意到 trunc 功能似乎非常慢。 图像的循环代码,像素的实际
oracle trunc()函数是最常用的函数之一,下面就为您介绍oracle trunc()函数的用法,供您参考,希望可以让您对oracle trunc()函数有更深的认识。 1.TRUNC(f
从 1.3.172 版本开始,有一个 TRUNC 函数,它模仿了 Oracle 的 TRUNC(TIMESTAMP)。实现过程中存在一个小问题。查询: select TRUNC(TIMESTAMP '
我有两个不同大小的变量“a”和“b”,见下文。我有几个问题: (1) 如何将“a”的值复制到“b”? (即扩展操作) (2) 如何将“b”的值复制到“a”? (即截断操作) 谢谢。 a = BitVe
select trunc('11.01') from dual 输出:11 jasper 报告中的 BigDecimal 数据类型是什么。是否有任何解决方法可以将其作为字符串。 最佳答案 Oracle
我需要限定来自 Oracle 数据库的查询以获取基于特定日期范围的报告 第一个查询 5pm-7am(昨天下午 5 点到今天早上 7 点之间) 第二个查询 早上 7 点到下午 5 点((昨天下午 5 点
我尝试在 Blender 2.49b Python 中使用 math.trunc 但我收到此错误 AttributeError: 'module' object has no attribute 't
我正在尝试使用以下方法截断 PostgreSQL 中的数字: SELECT trunc(31.71429,15); 我有这个输出: 31.714290000000000 但是在 Oracle 中我有这
我有旧的pascal代码 var i : longint; m : double; begin ..... i := trunc(m); 我必须将它转换为 C++ 代码。 这里很明显的
本文给大家分享的oracle trunc 函数处理日期格式的相关知识,非常具有参考价值,具体请看下文说明吧。 复制代码代码如下: select to_char(sys
我来自 SQL Server 世界,有人要求我弄清楚一段(古老的)Oracle 脚本是怎么回事。 CAVEAT: I don't have access to the Oracle server, I
在通过 Java 库翻译 Google Translate API 中的短语时,我突然得到了同样奇怪的标记。英语 → 瑞典语的示例包括: Vector graphics → vektor~~POS=T
为什么 从双中选择 trunc(to_date('23/06/2017','DD/MM/YYYY'), 'DAY'); 返回 2017年6月19日 不是预期的 2017年6月23日? 我们使用的是 O
我有一个包含每小时数据和值(value)的简单表格。我想计算每个月每日最大值的平均值。 该查询起初看起来很简单: WITH daily_max AS ( SELECT TRUNC(the_date
trunc()有什么区别和 as.integer() ? 为什么是 as.integer快点?谁能解释一下幕后发生了什么? 为什么trunc()返回类double而不是 integer ? x 43
我是一名优秀的程序员,十分优秀!