C++ 平方根元函数?

C++ 平方根元函数?,c++,templates,metaprogramming,sqrt,C++,Templates,Metaprogramming,Sqrt,是否可以使用具有以下签名的元函数计算整数的平方根: template<unsigned int N> inline double sqrt(); 模板内联双sqrt(); (或者使用constexpr关键字,我不知道什么是最好的)。 这样,编译时,sqrt()将被1.414…替换 对于这样一个函数,什么是最好的实现?我看到的问题是metaP有效地将枚举滥用到变量中。问题是枚举在内部被视为整数,这就排除了从中获取浮点值的可能性。但是,您可以创建自己的浮点格式,该格式可以创建两个结果

是否可以使用具有以下签名的元函数计算整数的平方根:

template<unsigned int N> inline double sqrt();
模板内联双sqrt();
(或者使用constexpr关键字,我不知道什么是最好的)。 这样,编译时,
sqrt()
将被
1.414…
替换


对于这样一个函数,什么是最好的实现?

我看到的问题是metaP有效地将枚举滥用到变量中。问题是枚举在内部被视为整数,这就排除了从中获取浮点值的可能性。但是,您可以创建自己的浮点格式,该格式可以创建两个结果,一个整数部分和一个指数。您仍然需要将其处理为浮点,如
Out=Sqrt::尾数*pow(10,Sqrt::exponent)。实际上,确定这些值是留给读者的一个练习,但是您可能需要向上扩展输入(以10的偶数幂次),计算根,并存储您之前使用的-power/2

要计算sqrt,首先将指数enum设置为合适的幂,例如“-4”(小数越小,小数越多,但要注意溢出)。然后将输入乘以“10^(-2*指数)”。在这种情况下,得到42*10^8=4200000000。然后取该值的根,将“64807”作为最终值。在运行时,计算“val*10^指数”=“64807*10^-4”=64807*0.0001=6.4807m并将其存储到浮点

额外的转换工作有点达不到目的,但是您可以通过将指数存储为10^k(即10^4),然后执行
out=sqrt::尾数/sqrt::exponent
来减少它

编辑我刚刚注意到,对于尾数/指数方法,指数的选择是任意的,只要它大于最终根的整数部分。它甚至可以是一个常数,这简化了元函数的设计。例如,在42的情况下,您可以选择“指数”始终为6000。然后将输入乘以6000^2,取乘积的整数根,然后在运行时将结果除以6000,得到根。它使用关系sqr(x*b^2)=sqr(x)*b,而不是将输出视为a*10^b。数学证明:

  • 42*6000*6000=1512000000
  • sqr(1512000000)=38884
  • 38884/6000=6.4806(平方为41.999)

    • 这可能不是您想要的,但我想确保您意识到,通常通过优化,编译器将在编译时计算结果。例如,如果您有以下代码:

      void g()
      {
        f(sqrt(42));
      }
      
      使用带有优化-O2的g++4.6.3,生成的汇编代码为:

         9 0000 83EC1C                subl    $28, %esp
        11 0003 DD050000              fldl    .LC0
        12 0009 DD1C24                fstpl   (%esp)
        13 000c E8FCFFFF              call    _Z1fd
        14 0011 83C41C                addl    $28, %esp
        16 0014 C3                    ret
        73                    .LC0:
        74 0000 6412264A              .long   1244009060
        75 0004 47EC1940              .long   1075440711
      
      sqrt函数从未被实际调用,而该值只是作为程序的一部分存储

      因此,要创建在技术上满足您需求的功能,您只需要:

      template<unsigned int N> inline double meta_sqrt() { return sqrt(N); }
      
      template inline double meta_sqrt(){return sqrt(N);}
      
      Eigen包含这个使用二进制搜索的
      meta\u sqrt

      template<int Y,
               int InfX = 0,
               int SupX = ((Y==1) ? 1 : Y/2),
               bool Done = ((SupX-InfX)<=1 ? true : ((SupX*SupX <= Y) && ((SupX+1)*(SupX+1) > Y))) >
                                      // use ?: instead of || just to shut up a stupid gcc 4.3 warning
      class meta_sqrt
      {
          enum {
        MidX = (InfX+SupX)/2,
        TakeInf = MidX*MidX > Y ? 1 : 0,
        NewInf = int(TakeInf) ? InfX : int(MidX),
        NewSup = int(TakeInf) ? int(MidX) : SupX
      };
        public:
          enum { ret = meta_sqrt<Y,NewInf,NewSup>::ret };
      };
      
      template<int Y, int InfX, int SupX>
      class meta_sqrt<Y, InfX, SupX, true>
      {
          public:  enum { ret = (SupX*SupX <= Y) ? SupX : InfX };
      };
      
      模板Y?1 : 0,
      NewInf=int(TakeInf)?InfX:int(MidX),
      NewSup=int(TakeInf)?int(MidX):SupX
      };
      公众:
      枚举{ret=meta_sqrt::ret};
      };
      模板
      类meta_sqrt
      {
      
      public:enum{ret=(SupX*SupX I谷歌搜索“模板元编程sqrt”我已经看到了这一点,但它只适用于整数的sqrt的整数部分。我希望在编译时得到浮点结果。因为
      sqrt
      是一个标准函数,我会使用
      sqrtt
      来代替。你能在编译时对浮点数做任何有意义的操作吗?包括平方根用牛顿求根法实现的函数。(查看自述文件示例)。你知道计算机不使用10的幂来存储浮点值,对吗?此外,你还交换了指数和尾数的概念。修复:)我知道十的幂,但因为我用的是小数,所以这没什么坏处。我还补充说,指数的选择是任意的。但是如果你使用二的幂,你可以使用
      ldexp
      组合指数和尾数,而不需要任何乘法或除法。大多数编译器可能都会计算出这两个数t编译时,但这不是保证。sqrt函数不返回
      constepr
      值;此函数的输出不能用作其他元函数的输入。这不是真正的元函数,也不能回答问题。