向 -Inf 舍入的快速浮点到整数公式:它是如何工作的?
Fast float-to-int formula with rounding toward -Inf: how does it work?
我一直在玩 x87 FPU 编程,我刚刚遇到以下从 float(32 位)转换为 int(32 位)的魔法:
flds from # number to convert from
fadds magic1 # add magic number 1 (???)
fstps to # store in destination as single-precision binary32
movl to,%eax # load float result as an int
subl $magic2,%eax # subtract magic number 2 (???)
sarl ,%eax # divide by 2
movl %eax,to # and look, here's the result!
.section .rodata
magic1: .float 6291456.0 # 3 * 2^21
.equ magic2, 0x4ac00000 # ???
.data
from: .float 31415.9265 # pick a number, any number...
to: .long 0 # result ends up here
(带有 GAS 指令的 AT&T 语法)
我已经试过了,它似乎有效(四舍五入到-infinity),但我完全不知道为什么!谁能解释一下它是如何工作的?
快速回答:
第一个神奇的数字强制重新缩放参数,以便整数部分的 LSbit 在小数部分变为 rightmost-but-one。
然后添加第二个魔法将擦除指数位。
关于最后除以2的必要性,IDK,肯定有一个额外的技术问题(可能与3.2^21而不是1.2^21的加法有关)。
我一直在玩 x87 FPU 编程,我刚刚遇到以下从 float(32 位)转换为 int(32 位)的魔法:
flds from # number to convert from
fadds magic1 # add magic number 1 (???)
fstps to # store in destination as single-precision binary32
movl to,%eax # load float result as an int
subl $magic2,%eax # subtract magic number 2 (???)
sarl ,%eax # divide by 2
movl %eax,to # and look, here's the result!
.section .rodata
magic1: .float 6291456.0 # 3 * 2^21
.equ magic2, 0x4ac00000 # ???
.data
from: .float 31415.9265 # pick a number, any number...
to: .long 0 # result ends up here
(带有 GAS 指令的 AT&T 语法)
我已经试过了,它似乎有效(四舍五入到-infinity),但我完全不知道为什么!谁能解释一下它是如何工作的?
快速回答:
第一个神奇的数字强制重新缩放参数,以便整数部分的 LSbit 在小数部分变为 rightmost-but-one。
然后添加第二个魔法将擦除指数位。
关于最后除以2的必要性,IDK,肯定有一个额外的技术问题(可能与3.2^21而不是1.2^21的加法有关)。