【问题标题】:how does Florian's Grisu2 algorithm work?Florian 的 Grisu2 算法是如何工作的?
【发布时间】:2015-03-09 11:59:53
【问题描述】:

遇到一个关于double转ascii的问题,搜索后得到了Florian的论文"Printing Floating-Point Numbers Quickly and Accurately with Integers",Grisu2算法真的很棒,速度也快很多。我理解了 Grisu2 的想法,但我不知道如何实现它,所以我得到了Florian's C implement,这对我来说有点复杂,我仍然不太了解 2 个函数:cached_power 和 digit_gen,任何知道 Grisu2 的人都可以帮忙我?

评论显示我的问题。

    //    cached_power function:

static const uint64_t powers_ten[] = {0xbf29dcaba82fdeae , 0xeef453d6923bd65a,...};  
//how do these numbers precomputed 
static const int powers_ten_e[] = {-1203 , -1200 , -1196 , -1193 , -1190 , ...};//and what do they mean?

static diy_fp_t cached_power(int k) 
{//does this function mean give k and return the normalized 10^k diy_fp_t?
      diy_fp_t res;
      int index = 343 + k;//why add 343?
      res.f = powers_ten[index];
      res.e = powers_ten_e[index];
      return res;
}

这个比较复杂

void digit_gen(diy_fp_t Mp, diy_fp_t delta,//Is Mp normalized?
char* buffer, int* len, int* K) 
{
     uint32_t div; int d, kappa; diy_fp_t one;
     one.f = ((uint64_t)1) << -Mp.e; one.e = Mp.e;//what if Mp.e is positive? what's the purpose of one?
     uint32_t p1 = Mp.f >> -one.e; /// Mp_cut// what does p1 mean?
     uint64_t p2 = Mp.f & (one.f - 1);//what does p2 mean?
     *len = 0; kappa = 3; div = TEN2;//why kappa=3 and div=100? is kappa related to div?
    while (kappa > 0) 
    {    /// Mp_inv1  //what does this loop mean?
         d = p1 / div;
         if (d || *len) buffer[(*len)++] = '0' + d;
         p1 %= div; kappa--; div /= 10;
         if ((((uint64_t)p1) << -one.e) + p2 <= delta.f) 
         { /// Mp_delta
             *K += kappa; return;
         }
    }
    do 
    {  //what does this loop mean?
         p2 *= 10;
         d = p2 >> -one.e;
         if (d || *len) buffer[(*len)++] = '0' + d; /// Mp_inv2
         p2 &= one.f - 1; kappa--; delta.f *= 10;// p2&=one.f-1 means what?
    } while (p2 > delta.f);
    *K += kappa;
}

【问题讨论】:

  • 我可能不必问,但您知道,在不使用 >2010 算法的情况下,您将在一个代码行中获得大多数情况下可接受的结果?
  • 那么阅读实际论文呢?
  • 这个link是否有具体问题无法解答? (由您提供)您引用的论文中的这句话:正确的打印成为许多语言规范的一部分,此外所有主要的 C 库(因此所有程序都依赖于 printf functions) 适应了准确的算法并现在打印正确的结果,表明它可能是您正在使用的 C 版本(如果它相当新)已经包含准确地打印的能力。 (第 1 页,第二列,第二段)
  • @deviantfan @ryyker 好吧,我确实知道如何使用sprintf 来获得正确的结果,但我的问题是,即使在阅读和思考了仔细看实际的纸张。

标签: c algorithm precision ieee-754 floating-point-conversion


【解决方案1】:

第一部分:

diy_fp_t 是一个浮点结构,尾数和指数作为单独的成员(不是很有趣,但在这里:https://github.com/miloyip/dtoa-benchmark/blob/master/src/grisu/diy_fp.h)。

cached_power(k) 的目的是计算 10^k 的值并将结果保存到diy_fp_t。因为这对计算机来说既不简单也不快速,作者拥有预先计算好的必要幂值(尽可能好)的数组(一个用于尾数,一个用于指数)(Grisu 不会使用除此之外的其他幂。一个解释见论文第 4 章和第 5 章)。

示例代码中的数组以10^(-343) 的值开头,即0xbf29dcaba82fdeae * 2^(-1203),=13774783565108600494 * 2^(-1203)10^(-342) 属于下一个数组位置,以此类推。而且因为-343有数组索引[0],所以先加上343。

【讨论】:

猜你喜欢
  • 2013-12-04
  • 2012-09-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-02
  • 2011-09-16
  • 1970-01-01
  • 2020-05-05
  • 2012-09-14
相关资源
最近更新 更多