标签: constantfolding

为什么D + 0.1 + 0.2 == 0.3?

assert(0.1 + 0.2 != 0.3); // shall be true
Run Code Online (Sandbox Code Playgroud)

是我最喜欢的检查,语言使用本机浮点运算.

C++

#include <cstdio>

int main()
{
   printf("%d\n", (0.1 + 0.2 != 0.3));
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

1
Run Code Online (Sandbox Code Playgroud)

http://ideone.com/ErBMd

蟒蛇

print(0.1 + 0.2 != 0.3)
Run Code Online (Sandbox Code Playgroud)

输出:

True
Run Code Online (Sandbox Code Playgroud)

http://ideone.com/TuKsd

其他例子

为什么D不适用?理解D使用本机浮点数.这是一个错误吗?他们是否使用某些特定的数字代表?别的什么?很混乱.

d

import std.stdio;

void main()
{
   writeln(0.1 + 0.2 != 0.3);
}
Run Code Online (Sandbox Code Playgroud)

输出:

false
Run Code Online (Sandbox Code Playgroud)

http://ideone.com/mX6zF


UPDATE

感谢LukeH.这是在那里描述的浮点常数折叠的效果.

码:

import std.stdio;

void main()
{
   writeln(0.1 + 0.2 != 0.3); // …
Run Code Online (Sandbox Code Playgroud)

floating-point d floating-accuracy constantfolding

75
推荐指数
3
解决办法
2万
查看次数

为什么表达式而不是常量,在C for循环的条件中?

在许多编程比赛中,我看到有人写这种类型的for-loop

for(i = 0; i < (1 << 7); i++)
Run Code Online (Sandbox Code Playgroud)

除非我遗漏了什么,否则就是这样

for(i = 0; i < 128; i++)
Run Code Online (Sandbox Code Playgroud)

为何使用该(1 << 7)版本?
每次不必要的开销是不是计算条件?

c expression for-loop coding-style constantfolding

57
推荐指数
5
解决办法
3909
查看次数

log(10.0)可以编译但是log(0.0)不能吗?

对于以下C源代码:

#include <math.h>

int main(void)
{
    double          x;

    x = log(0.0);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我编译时gcc -lm,我得到:

/tmp/ccxxANVH.o: In function `main':
a.c:(.text+0xd): undefined reference to `log'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

但是,如果我替换log(0.0)log(10.0),那么它可以成功编译.

我不太明白这一点,因为无论它们是否具有数学意义,它们都应该编译 - 没有语法错误.有人能解释一下吗?

以防万一,我的gcc -v输出:

Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 …
Run Code Online (Sandbox Code Playgroud)

c gcc math.h constantfolding

46
推荐指数
2
解决办法
2714
查看次数

为什么GCC对C++ <cmath>比C <math.h>更有效地实现isnan()?

这是我的代码:

int f(double x)
{
  return isnan(x);
}
Run Code Online (Sandbox Code Playgroud)

如果我#include <cmath>得到这个集会:

xorl    %eax, %eax
ucomisd %xmm0, %xmm0
setp    %al
Run Code Online (Sandbox Code Playgroud)

这是相当聪明的:如果x与其自身的比较是无序的,则ucomisd设置奇偶校验标志,意味着x是NAN.然后setp将奇偶校验标志复制到结果中(只有一个字节,因此最初清除%eax).

但是,如果我#include <math.h>得到这个集会:

jmp     __isnan
Run Code Online (Sandbox Code Playgroud)

现在代码不是内联的,并且__isnan函数当然没有更快的ucomisd指令,所以我们已经跳过没有任何好处.如果我将代码编译为C,我会得到同样的东西.

现在如果我将isnan()调用更改为__builtin_isnan(),我会得到简单的ucomisd指令指令,无论我包含哪个头,它也可以在C中工作.同样,如果我只是return x != x.

所以我的问题是,为什么C <math.h>头提供的效率isnan()低于C++ <cmath>头?人们真的希望使用__builtin_isnan(),如果是,为什么?

我在x86-64上使用-O2-O3优化测试了GCC 4.7.2和4.9.0 .

c c++ optimization nan constantfolding

42
推荐指数
1
解决办法
4714
查看次数

C++常量折叠素数循环

说完看了一眼前面的问题1,2,我在想,如果我可以强制编译器以下代码打印素数进行常量折叠.

#include <iostream>

using namespace std;

inline bool is_prime(int n)
{
    if(n<2)
        return false;
    for(int i=2;i*i<=n;i++)
        if(n%i==0)
            return false;
    return true;
}

int main()
{
    for(int i=0;i<20;i++)
        if(is_prime(i))
            cout<<i<<endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我通过以下方式构建它:

g++ -O3 -S main.cpp -o main.asm
Run Code Online (Sandbox Code Playgroud)

结果是一些:

2,3,5,7,11,13,17,19
Run Code Online (Sandbox Code Playgroud)

我想强制编译看看类似的代码

for(int x:{2,3,5,7,11,13,17,19})
    cout<<x<<endl;
Run Code Online (Sandbox Code Playgroud)

要么

cout<<  2 <<endl;
cout<<  3 <<endl;
cout<<  5 <<endl;
cout<<  7 <<endl;
cout<< 11 <<endl;
cout<< 13 <<endl;
cout<< 17 <<endl;
cout<< 19 <<endl;
Run Code Online (Sandbox Code Playgroud)

但阅读大会表明没有发生.

我甚至使用__builtin_expect但它没有用.

有没有办法强制编译器优化器读取for循环并使用输出数据已知的优势?

我想在不使用模板元编程的情况下完成它. …

c++ g++ compiler-optimization constantfolding

10
推荐指数
1
解决办法
288
查看次数

为什么要避免在Java中不断折叠?什么时候?

我在slf4j中看到了一些代码,如下所示.我不知道为什么要避免在这里不断折叠.有必要这样做吗?或者只是最好的做法.这样做有什么好处?

谢谢.

/**
  * Declare the version of the SLF4J API this implementation is compiled against. 
  * The value of this field is usually modified with each release. 
  */
// to avoid constant folding by the compiler, this field must *not* be final
public static String REQUESTED_API_VERSION = "1.6";  // !final**
Run Code Online (Sandbox Code Playgroud)

java compiler-construction slf4j constantfolding

9
推荐指数
1
解决办法
820
查看次数

gcc复数常数折叠

似乎gcc对复杂的常量折叠有一些限制.这是一个例子:

static inline unsigned int DJBHash(const char *str)
{
   int i;
   unsigned int hash = 5381;

   for(i = 0; i < strlen(str); i++)
   {
      hash = ((hash << 5) + hash) + str[i];   
   }

   return hash;
}

int f(void)
{   
    return DJBHash("01234567890123456");
}
Run Code Online (Sandbox Code Playgroud)

当使用-O3优化级别(gcc 4.8)运行时,它很好地展开了DJBHash中的循环,并在编译期间计算该字符串的哈希值.

但是,当使字符串长一个字符时,return DJBHash("012345678901234567");它不再折叠它并生成带有条件跳转指令的循环.

我想将任意长度的文字字符串折叠为其哈希值作为编译时常量.
这可以吗?

澄清

我的问题是关于gcc的常量折叠优化(请参阅标题 - 请不要删除gcc编译器标签)
这里的许多答案试图用模板或constexpr解决问题.很高兴知道这些选项,并感谢发布它们为所有人的利益.但是,他们没有直接回答我的问题.

实际上,我正在使用gcc端口,因此我可以根据需要更改和构建gcc源代码.但我只限于C,我想在这个范围内解决这个问题.

c compiler-construction gcc compiler-optimization constantfolding

9
推荐指数
3
解决办法
2276
查看次数

O = Deparse是如何工作的,Perl是否具有折叠常数数组?

我想知道,确实-MO=Deparse向您展示了所有Perl优化,为什么不在Perl 5.10中折叠?

$ perl -MO=Deparse -e'[qw/foo bar baz/]->[0]'
['foo', 'bar', 'baz']->[0];
-e syntax OK
Run Code Online (Sandbox Code Playgroud)

IRC的一些人认为O=Deparse可能没有全部显示,但它确实显示了一些不断折叠.

$ perl -MO=Deparse -e'use constant "foo" => "bar"; foo'
use constant ('foo', 'bar');
'???';
-e syntax OK
Run Code Online (Sandbox Code Playgroud)

如果我明确写出常量sub,结果相同.虽然可预测,但是文档中constant.pm包含的是创建常量列表而不是常量数组也很有趣.我假设这不仅仅是像标量常量那样折叠,而是需要在每次调用时创建新数组的开销.

$ perl -MO=Deparse -e'use constant foo => qw/foo bar baz/; (foo)[0]'
use constant ('foo', ('foo', 'bar', 'baz'));
(foo)[0];
-e syntax OK
Run Code Online (Sandbox Code Playgroud)

我能得出的唯一结论-MO=Deparse是显示所有折叠,而常量数组在Perl中没有优化?是这样吗?它有技术原因吗?

perl compiler-optimization perl5.10 constantfolding

8
推荐指数
2
解决办法
800
查看次数

减去uint和int以及常量折叠

基于这个有趣的问题:在Nicholas Carey的回答中提到的添加int和uint以及使用常量折叠进行操作时,我偶然发现了编译器看似不一致的行为:

请考虑以下代码段:

int i = 1;
uint j = 2;
var k = i - j;
Run Code Online (Sandbox Code Playgroud)

这里编译器正确解析klong.这种特殊行为在规范中有明确定义,如前面提到的问题的答案中所解释的那样.

让我感到惊讶的是,在处理文字常量常量时,行为会发生变化.阅读Nicholas Carey的回答我意识到行为可能不一致所以我检查并确定:

const int i = 1;
const uint j = 2;
var k = i - j; //Compile time error: The operation overflows at compile time in checked mode.
k = 1 - 2u; //Compile time error: The operation overflows at compile time in …
Run Code Online (Sandbox Code Playgroud)

c# constantfolding

8
推荐指数
1
解决办法
581
查看次数

什么是java编译器中的常量折叠?

可能重复:
java中是否有任何称为"常量折叠"的概念?

嗨,我遇到过Java编译器使用称为Constant Folding的东西.这是什么?它是如何影响的?

java core constantfolding

7
推荐指数
1
解决办法
3697
查看次数