浮点除法是否足以准确确定箱号?

时间:2014-11-04 19:28:10

标签: floating-accuracy

我正在努力准确地说明本初子午线的交叉点 我遇到了关于IEEE浮点运算的以下问题 (舍入到最近):

n 为整数, d 为小正数。确实

y = n * 360 - d < n * 360

保证楼层( y / 360)< 名词的?这里所有操作(* - < / floor)都是 被理解为浮动操作(使用例如双精度IEEE)。

如果这个问题中的360被其他一些积极的东西取代怎么办? 浮点数。 (每当浮动时都会出现同样的问题 点数被分配给均匀分布的箱。)

2 个答案:

答案 0 :(得分:0)

n * 360 - d < n * 360 - &gt; 0 - d < 0 - &gt; d > 0为真,因为“ d (是) small 正数”。

到目前为止,n的价值无关紧要。


y = n * 360 - d - &gt; y/360 = n - d/360 - &gt;

0.0 <= q < 1.0
floor(y/360) + q = n - d/360 - &gt; floor(y/360) - n = -q - d/360

对于qd的所有值,-q - d/360 < 0 - &gt;

floor(y/360) - n < 0 - &gt; floor(y/360) < nQ.E.D.


如果360被x替换为任何大于0的整数,答案仍然是相同的。如果将x替换为任何数字&gt; = 1.0,我认为也是如此。必须考虑0 < x < 1

d最小到目前为止无关紧要 - 只是它是一个正数(d > 0)。

答案 1 :(得分:0)

经过一些实验,我想我可以提供部分答案。让我来 改写问题:写一个函数

int bin(double x, double m)

计算

int(floor(x/m))

准确。假设 m 为正,结果在范围内 中间体

第一次尝试是

int bin0(double x, double m) {
  return int(std::floor(x / m));
}

但是对于 m = 360.0和 x = -denorm_min(0是 返回而不是-1)。

由于此故障只是 x 接近于零,因此第二次尝试是

int bin1(double x, double m) {
  int n = int(std::floor(x / m));
  return n == 0 && x < 0 ? -1 : n;
}

相信这会返回 n 提供的确切答案 n * m 完全可以表示为双。对于 m = 360.0,这包括所有 n 可表示为32位整数。我对吗?一个证明就是 太好了!

如果这个条件不成立,例如 m = 0.1,那么我能做到最好 想出来就是

int bin2(double x, double m) {
  double z = std::fmod(x, m);
  return int(std::floor((x - z)/m + 0.5)) + (z < 0 ? -1 : 0);
}

这总是会返回正确的结果吗?是否有一些&#34;清洁&#34; 溶液

ADDENDUM:在我的应用程序中,我只需要获得奇偶校验 箱号(偶数或奇数)。 (我的应用是测量a的面积 测地线多边形,我需要跟踪边缘是否环绕 极点偶数或奇数次。)所以chux的建议使用 remquo是一个很好的。不幸的是(1)std :: remquo需要C ++ 11和 (2)更严重的是,glquo的glibc实现是错误的;看到 这bug report。所以我最终基本上做了

int binparity(real x, real m) {
  // return the parity of int(floor(x/m))
  x = std::fmod(x, 2 * m);
  return (x >= 0 && x < m) || x < -m ? 0 : 1
}