pow 函数中发生了什么?

2023-12-22

我在这里看到了各种描述奇怪行为的答案powC 中的函数。
但我在这里有一些不同的问题要问。

在下面的代码中我已经初始化了int x = pow(10,2) and int y = pow(10,n) (int n = 2).

在第一种情况下,当我打印它显示的结果时100在另一种情况下,结果是99.

我知道pow回报double它在存储时被截断int,但我想问为什么输出会不同。

CODE1

#include<stdio.h>
#include<math.h>
int main()
{
     int n = 2;
     int x;
     int y;
     x = pow(10,2);   //Printing Gives Output 100   
     y = pow(10,n);   //Printing Gives Output 99


     printf("%d %d" , x , y);

}

Output : 100 99

为什么输出结果不同。 ?

我的gcc版本是4.9.2

Update :

Code 2

int main()
    {
         int n = 2;
         int x;
         int y;
         x = pow(10,2);   //Printing Gives Output 100   
         y = pow(10,n);   //Printing Gives Output 99
         double k = pow(10,2);
         double l = pow(10,n);


         printf("%d %d\n" , x , y);
         printf("%f %f\n" , k , l);

    }

输出 :100 99
100.000000 100.000000

Update 2组装说明 适用于CODE1

生成的组装指令海湾合作委员会4.9.2 using gcc -S -masm=intel :

    .LC1:
    .ascii "%d %d\0"
    .text
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    push    ebp
    mov ebp, esp
    and esp, -16
    sub esp, 48
    call    ___main
    mov DWORD PTR [esp+44], 2
    mov DWORD PTR [esp+40], 100      //Concerned Line
    fild    DWORD PTR [esp+44]
    fstp    QWORD PTR [esp+8]
    fld QWORD PTR LC0
    fstp    QWORD PTR [esp]
    call    _pow                    //Concerned Line
    fnstcw  WORD PTR [esp+30]
    movzx   eax, WORD PTR [esp+30]
    mov ah, 12
    mov WORD PTR [esp+28], ax
    fldcw   WORD PTR [esp+28]
    fistp   DWORD PTR [esp+36]
    fldcw   WORD PTR [esp+30]
    mov eax, DWORD PTR [esp+36]
    mov DWORD PTR [esp+8], eax
    mov eax, DWORD PTR [esp+40]
    mov DWORD PTR [esp+4], eax
    mov DWORD PTR [esp], OFFSET FLAT:LC1
    call    _printf
    leave
    ret
    .section .rdata,"dr"
    .align 8
LC0:
    .long   0
    .long   1076101120
    .ident  "GCC: (tdm-1) 4.9.2"
    .def    _pow;   .scl    2;  .type   32; .endef
    .def    _printf;    .scl    2;  .type   32; .endef

我知道 pow 返回 double 并且在存储为 int 时会被截断,但我想问为什么输出会有所不同。

如果您还没有的话,您必须首先放弃浮点数在任何方面都是合理或可预测的想法。double only 近似实数以及几乎任何你用 a 做的事情double很可能是实际结果的近似值。

也就是说,正如你所意识到的,pow(10, n)结果是这样的值99.99999999999997,这是精确到 15 位有效数字的近似值。然后你告诉它截断为小于该值的最大整数,因此它丢弃了其中的大部分。

(旁白:很少有good转换的原因double to an int。通常您应该将其格式化为显示格式,例如sprintf("%.0f", x),它可以正确舍入,或者使用floor函数,它可以处理可能超出范围的浮点数int。如果这些都不适合您的目的,例如在货币或日期计算中,您可能根本不应该使用浮点数。)

这里发生了两件奇怪的事情。第一的,why is pow(10, n)不准确?10、2 和 100 都可以精确表示为double。我能提供的最好答案是您正在使用的 C 标准库有一个错误。 (编译器和标准库,我假设是 gcc 和 glibc,是根据不同的发布计划和由不同的团队开发的。如果pow返回不准确的结果,这可能是 glibc 中的错误,而不是 gcc 中的错误。)

在你的问题的评论中,发现了一个与 FP 舍入有关的 glibc bug https://sourceware.org/bugzilla/show_bug.cgi?id=3976这可能相关并且另一个问答 https://stackoverflow.com/questions/32353301/will-intpown-m-be-wrong-for-some-positive-integers-n-m更详细地说明了为什么会发生这种情况以及它如何不违反 C 标准。 chux的回答也解决了这个问题。 (C 不需要实现IEEE 754 https://en.wikipedia.org/wiki/IEEE_floating_point,但即使这样做了,pow不需要使用正确的舍入。)我仍然将其称为 glibc bug,因为它是一个不受欢迎的属性。

(也可以想象,尽管不太可能,您的处理器的 FPU 是错误的。)

Second, why is pow(10, n)不同于pow(10, 2)?这个要容易得多。 gcc 优化了可以在编译时计算结果的函数调用,因此pow(10, 2)几乎可以肯定正在优化100.0。如果你查看生成的汇编代码,你会发现只有一次调用pow.

The GCC 手册,第 6.59 节 https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#Other-Builtins描述了哪些标准库函数可以以这种方式处理(点击链接查看完整列表):

其余功能是出于优化目的而提供的。

除了具有库等效项(例如下面讨论的标准 C 库函数)或扩展为库调用的内置函数之外,GCC 内置函数始终内联扩展,因此没有相应的入口点,并且它们的地址不能被获得。尝试在函数调用以外的表达式中使用它们会导致编译时错误。

[...]

ISO C90 函数 abort、abs、acos、asin、atan2、atan、calloc、ceil、cosh、cos、exit、exp、fabs、floor、fmod、fprintf、fputs、frexp、fscanf、isalnum、isalpha、iscntrl、isdigit、 isgraph、islower、isprint、ispunct、isspace、isupper、isxdigit、tolower、toupper、实验室、ldexp、log10、日志、malloc、memchr、memcmp、memcpy、memset、modf、pow、 printf、putchar、puts、scanf、sinh、sin、snprintf、sprintf、sqrt、sscanf、strcat、strchr、strcmp、strcpy、strcspn、strlen、strncat、strncmp、strncpy、strpbrk、strrchr、strspn、strstr、tanh、tan 、vfprintf、vprintf 和 vsprintf都被识别为内置函数 unless -fno-builtin已指定(或-fno-builtin-function是为单个函数指定的)。

所以看来你可以禁用这种行为-fno-builtin-pow.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pow 函数中发生了什么? 的相关文章

  • 为什么我应该使用内联代码? [复制]

    这个问题在这里已经有答案了 我是一名 C C 开发人员 这里有几个始终困扰我的问题 常规 代码和内联代码之间有很大区别吗 主要区别是什么 内联代码只是宏的一种 形式 吗 选择内联代码时必须进行什么样的权衡 Thanks 表现 正如之前的答案
  • 是否保证 sizeof(T[N]) == N * sizeof(T) ?

    我一直假设 N 个元素类型的数组的大小T 由返回sizeof保证正好是N次sizeof T The 对这个问题的评论 https stackoverflow com questions 46457449 is it always the c
  • 命名管道客户端无法连接到作为网络服务运行的服务器

    我有一个服务在网络服务帐户下运行 该服务只是设置一个命名管道并侦听连接 NamedPipeServerStream listeningPipe new NamedPipeServerStream ourservicepipe PipeDir
  • OpenCV SVM 给出奇怪的预测结果

    我对 OpenCV 和支持向量机都很陌生 我想使用 SVM 训练具有两个标签的数据集 然后预测给定集合的标签 我当前的集合包含大约 600 行 具有相等的类分布 1 为 300 行 1 为 300 行 包含 34 列 这是我当前用于设置 O
  • C++:字符串流有什么好处?

    谁能告诉我一些在 C 中使用字符串流的实际例子 即使用流插入和流提取运算符输入和输出到字符串流 您可以使用字符串流来转换任何实现operator lt lt 到一个字符串 include
  • C++ 并行任务的开销

    我有以下简单的功能 include
  • 使用 LINQ 展平嵌套字典

    所以我有一本形式的字典Dictionary
  • 将视频上传/保存到数据库或文件系统

    我以前从未尝试过保存视频 所以我对此了解不多 我知道如果视频很小 我可以转换为字节数组并保存到数据库 但是为了提高效率 我想了解如何将任何上传的视频保存到我的服务器文件中 然后只保存该文件的文件路径我的数据库表中的视频 我完全不知道如何开始
  • Web浏览器控件:如何捕获文档事件?

    我正在使用 WPF 的 WebBrowser 控件加载一个简单的网页 在这个页面上我有一个锚点或一个按钮 我想在我的应用程序后面的代码中 即在 C 中 捕获该按钮的单击事件 WebBrowser 控件是否有办法捕获加载页面元素上的单击事件
  • 是否自初始化 'A a = a;'允许吗?

    此代码在运行时在复制构造函数中失败 但编译器 MSVS2008 没有发出警告 您能解释一下 最好引用标准 这段代码是否非法或什么 我理解 A a a 永远不应该写在第一位 但我正在寻找理论背景 class A public A p new
  • 在 Linq 查询中使用动态列名称

    foreach Dimension dimensions in Enum GetValues typeof Dimension var r new ReferenceTable dimensions referenceItems List
  • 将旧的 Unity 代码升级到 Unity 5

    在触发按钮上播放动画的代码似乎不起作用 我在 Youtube 上看到了一个视频 内容很简单animation Play 它可以在该视频上运行 但我无法让它在我的计算机上运行 我做错了什么还是团结改变了它 请帮助我在网上找不到解决方案 所有
  • 如何将输出重定向到 boost 日志?

    我有一个使用boost log的C 程序 我加载了用户提供的动态链接库 我想将 stderr 重定向到 boost 日志 以便用户的库随时执行以下操作 std cerr lt lt Some stuff 它产生相同的结果 BOOST LOG
  • WCF 服务中的缓冲区大小

    我们有一个 WCF 服务 它执行某些存储过程并将结果返回给 silverlight 客户端 某些存储过程最多返回 80K 行 下面给出的是 web config 中服务的设置
  • Rx 在不同的线程上生产和消费

    我试图通过此处的示例代码来简化我的问题 我有一个生产者线程不断地输入数据 并且我尝试在批次之间添加时间延迟来对其进行批处理 以便 UI 有时间渲染它 但结果并不如预期 生产者和消费者似乎在同一个线程上 我不希望批处理缓冲区在正在生成的线程上
  • NSubstitute - 测试特定的 linq 表达式

    我在当前正在开发的 MVC 3 应用程序中使用存储库模式 我的存储库界面如下所示 public interface IRepository
  • Membership.ValidateUser() 的目的是什么

    我一直在学习有关MembershipProvider类 我认为Membership ValidateUser 方法应该用于登录用户 然而我刚刚了解到有一个FormsAuthentication Authenticate 目的是什么Valid
  • 调用泛型类的方法

    这是上下文 我尝试编写一个映射器来动态地将域模型对象转换为 ViewModel 对象 我遇到的问题是 当我尝试通过反射调用泛型类的方法时 出现此错误 System InvalidOperationException 无法对 Contains
  • 打印任何类型的数组和列表的通用方法[重复]

    这个问题在这里已经有答案了 每当我调试一段涉及整数 双精度 字符串等数组或列表的代码时 有时我更喜欢打印它们 我为此所做的是为不同类型编写重载的 printArray printList 方法 for e g 我可能有这 3 种方法来打印各
  • 小数精度

    我使用小数类型进行高精度计算 货币 但我今天遇到了这个简单的划分 1 1 37 这应该再次得到 37 http www wolframalpha com input i 1 2F 281 2F37 29 http www wolframal

随机推荐

  • 删除滚动条但不删除滚动功能[重复]

    这个问题在这里已经有答案了 我知道你可以定义溢出 隐藏 在 HTML 正文上删除滚动条 但我希望仍然能够使用鼠标上的箭头或滚轮滚动 预先感谢您的任何帮助 编辑 感谢您有关悬停滚动条和自定义栏的所有建议 还要感谢您对删除滚动条影响用户体验的所
  • 捆绑包和文件访问

    我已向我的项目添加了一系列文件夹 使用 添加现有文件 选项 这会导致文件夹内容在 Xcode 中显示为蓝色文件夹 以下作品 NSString imageName NSString stringWithFormat File 03 image
  • PowerShell 范围标识符

    我是 PowerShell 新手 试图更好地理解范围 有没有办法从范围内识别范围 某些变量或函数可以给我某种范围名称或范围 Guid 或范围 Id 例如 我如何知道本地范围是否是全局范围 例如 我如何知道本地范围是否是全局范围 bool i
  • 如何验证传递给“PrincipalContext”的凭据

    这是后续我之前的问题 https stackoverflow com questions 50055073 testing a principalcontext using validatecredentialsnull null beha
  • ant 的 componentdef 错误

    我有一个相对较旧的 Grails 应用程序 它使用 ant 来构建应用程序 在测试服务器中 它构建没有任何问题 但是当我尝试在我的电脑上运行它时 我收到一致的错误 Caused by jar file C ant apache ant 1
  • Scala:理解参数多态性

    有什么区别 def drop1 A l List A l tail and def drop1 l List Int l tail 假设用法看起来像 drop1 List 1 2 3 何时应该使用其中之一 为什么 虽然我可以理解第二个例子
  • Swift“文本”不可用:自 iOS7 起已弃用 API。文本标签不起作用

    我一直有这个错误 我已经看到使用 textLabel text 回答了其他问题 但它在我的情况下不起作用 我是 swift 的新手 所以有人可以解释一下为什么以及如何解决这个问题 你需要打开包装textLabel通过使用 after tex
  • 将可变 Arc 引用传递给 hyper service_fn 处理程序时出现问题

    我一直在尝试以下 显示相关导入和代码 use std sync Arc Mutex use std thread use hyper rt self Future Stream use hyper service service fn us
  • 设置图例符号不透明度

    我正在绘制带有半透明 x 标记 20 alpha 的绘图 如何使图例中的标记以 100 不透明度显示 import matplotlib pyplot as plt plt plot date x xaxis y yaxis marker
  • C# 代码片段和汇编 TBB 有什么区别?

    据我了解 C 代码片段和 NET 程序集为模块化模板开发提供相同的功能 我们在 CME 中管理代码片段 在 Visual Studio 中管理汇编代码 但在模板生成器中使用相同的方式 在代码方面 我可以创建一个C 代码片段模板构建块 TBB
  • 更改 XSL 转换中的命名空间值?

    我不确定这是否可能 因为我对 XSLT 之类的东西非常陌生 但也许你们中的一些人可以在这里帮助我 这有点棘手 我在互联网上没有找到类似的东西 问题是我有一个输入 xml 其中声明了名称空间和所有内容 我只需要对其进行轻微更改 添加或删除属性
  • Django 静态文件应用程序帮助

    我对 Django 有一个小问题静态文件应用程序 https docs djangoproject com en dev ref contrib staticfiles 我已经添加了 django contrib staticfiles 到
  • React.js - Flux 与全局事件总线

    与全局事件总线相比 使用 Flux 有何优势 我认为调度程序就是所需要的 组件将带有数据的 用户事件 发布到调度程序 调度程序执行订阅商店的处理程序 处理程序发布 更新事件 以及商店的更新属性 调度程序执行订阅组件的处理程序 并使用存储的更
  • 在 python 中将 RAW 图像转换为 TIFF 但保留元数据

    我尝试将原始图像转换为 tiff 但我希望它保留元数据 这是我之前使用的代码 import rawpy imageio os with rawpy imread path as raw rgb raw postprocess imageio
  • Python 浮点格式

    我已经看到了一些与此相关的问题 但我读到的这些问题都没有帮助我真正理解为什么我想做的事情失败了 所以我有一堆浮点值 它们有不同的精度 有些是 0 1 其他是 1 759374 等 我想格式化它们 以便它们全部采用我尝试做的 0 000000
  • ilasm / ildasm 的 Java 字节码等效项

    对于 CIL MSIL 我可以在文本编辑器中编写代码并使用 ilasm ildasm 进行编译 反编译 我可以使用 Reflector 来查看 NET 类生成的 CIL 在Java世界中 javap c显示反汇编的字节代码 如何编译 Jav
  • 保存和删除 NSManagedObject 和 NSManagedObjectContext

    三个问题 但它们都是相关的 如果您愿意 我可以将它们分为三个问题 以便您获得更多学分 如果您愿意我这样做 请告诉我 我有以下代码允许我访问 NSManagedObject self managedObjectContext STAppDel
  • 使用 ipdb 默认进入粘性模式

    调试时使用ipdb 我发现输入很有用sticky模式遵循代码源 有没有办法在粘滞模式下自动输入而无需输入sticky 是的 从REAMDE https github com mverteuil pdbpp configuration and
  • 在 XAML 中为一个事件添加多个事件处理程序?

    在程序代码中可以执行以下操作 Add two event handler for the button click event button1 Click new RoutedEventHandler button1 Click 1 but
  • pow 函数中发生了什么?

    我在这里看到了各种描述奇怪行为的答案powC 中的函数 但我在这里有一些不同的问题要问 在下面的代码中我已经初始化了int x pow 10 2 and int y pow 10 n int n 2 在第一种情况下 当我打印它显示的结果时1