c++ - 了解 double 到 int64_t 的转换

标签 c++ double

所以我有两个函数,一个只是从 double 转换为 int64_t,另一个调用 std::round:

std::int64_t my_cast(double d)
{
  auto t = static_cast<std::int64_t>(d);
  return t;
}

std::int64_t my_round(double d)
{
  auto t = std::round(d);
  return t;
}

它们工作正常:cast(3.64) = 3round(3.64) = 4。但是,当我查看程序集时,他们似乎在做同样的事情。所以想知道他们如何得到不同的结果?

$ g++ -std=c++1y -c -O3 ./round.cpp -o ./round.o 
$ objdump -dS ./round.o
./round.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_Z7my_castd>:
   0:   f2 48 0f 2c c0          cvttsd2si %xmm0,%rax
   5:   c3                      retq
   6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
   d:   00 00 00

0000000000000010 <_Z8my_roundd>:
  10:   48 83 ec 08             sub    $0x8,%rsp
  14:   e8 00 00 00 00          callq  19 <_Z7my_castd+0x19> <========!!!
  19:   48 83 c4 08             add    $0x8,%rsp
  1d:   f2 48 0f 2c c0          cvttsd2si %xmm0,%rax
  22:   c3                      retq

Disassembly of section .text.startup:

0000000000000030 <_GLOBAL__sub_I__Z7my_castd>:
  30:   48 83 ec 08             sub    $0x8,%rsp
  34:   bf 00 00 00 00          mov    $0x0,%edi
  39:   e8 00 00 00 00          callq  3e <_GLOBAL__sub_I__Z7my_castd+0xe>
  3e:   ba 00 00 00 00          mov    $0x0,%edx
  43:   be 00 00 00 00          mov    $0x0,%esi
  48:   bf 00 00 00 00          mov    $0x0,%edi
  4d:   48 83 c4 08             add    $0x8,%rsp
  51:   e9 00 00 00 00          jmpq   56 <_Z8my_roundd+0x46>

我不确定 14 行上的那个 callq 的目的是什么,但即便如此,my_castmy_round 似乎只是在做一个 cvttsd2si ,我相信这是用截断的转换。

但是,正如我之前提到的,这两个函数在相同的输入上产生不同(正确)的值(比如 3.64)

发生了什么?

最佳答案

汇编输出更有用(g++ ... -S && cat round.s):

...
_Z7my_castd:
.LFB225:
    .cfi_startproc
    cvttsd2siq  %xmm0, %rax
    ret
    .cfi_endproc
...
_Z8my_roundd:
.LFB226:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    call    round             <<< This is what callq 19 means
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    cvttsd2siq  %xmm0, %rax
    ret
    .cfi_endproc

如你所见,my_round 调用std::round 然后执行cvttsd2siq 指令。这是因为std::round(double)返回double,所以它的结果还是要转换成int64_t。这就是 cvttsd2siq 在你的两个函数中所做的。

关于c++ - 了解 double 到 int64_t 的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36148516/

相关文章:

c++ - Conv2D vs Depthwise Conv2D 计算

c++ - 使用静态函数变量与类变量来存储一些状态

c++ - SWIG - 包装 std::pair 字符串时内存泄漏

c++ - 当成员析构函数运行时,类具有什么类型的虚函数?

qt - QML 中的 Double 现在完全等于 Real 吗?

c++ - 简单密集光流程序 calcOpticalFlowFarneback() openCV 3.2 cpp

c - 如何在C中不使用科学记数法显示大双数?

swift - 添加字典 swift 3 中包含的 double

swift - 无法在 Double - Swift 中转换和使用字符串值