如何检查long long是否适合双变量

时间:2016-04-18 16:03:03

标签: c type-conversion floating-accuracy

我想检查一个long long变量是否可以安全地转换为double。 DBL_MAX没有帮助,因为有一些整数小于不能用double表示的整数,而一些大于2^53的整数仍然适合。

有可靠的方法吗? 编译器能否优化出类似下面的语句?

(long long)((double)a) == a(其中along long

这不要求一个可以表示为double的最大整数,我要求一个通用函数可以检查我是否可以完全转换任何 {{1值没有错误加倍。

2 个答案:

答案 0 :(得分:1)

OP的方法是个好的开始。

(long long)((double)a) == a

然而有问题。例如。 long long a = LLONG_MAX; ((double)a)结果的舍入值超过LLONG_MAX

以下肯定不会溢出double (病态异常:LLONG_MIN超过-DBL_MAX)。

volatile double b = (double) a;

转换回long long并针对a进行测试就足以达到OP的目标。只需确保b处于long long范围内。 @gnasher729我们假设2补,double使用FLT_RADIX != 10。在这种情况下,最低long long是2的幂,最高是2的幂减去1,并且通过仔细计算{{1}可以精确地转换为double限制,如下。

long long

[编辑简化 - 更一般]

只有当bool check_ll(long long a) { constant double d_longLong_min = LLONG_MIN; constant double d_longLong_max_plus_1 = (LLONG_MAX/2 + 1)*2.0; volatile double b = (double) a; if (b < d_longLong_min || b >= d_longLong_max_plus_1) { return false; } return (long long) b == a; } 不使用2补码时才需要b LLONG_MIN附近的long long测试

bool check_ll2(long long a) {
  volatile double b = (double) a;
  constant double d_longLong_max_plus_1 = (LLONG_MAX/2 + 1)*2.0;
  #if LLONG_MIN == -LLONG_MAX
    constant double d_longLong_min_minus_1 = (LLONG_MIN/2 - 1)*2.0;;
    if (b <= d_longLong_min_minus_1 || b >= d_longLong_max_plus_1) {
      return false;
    }
  #else
    if (b >= d_longLong_max_plus_1) {
      return false;
    }
  #endif
  return (long long) b == a;
}

我不希望编译能够优化(long long)((double)a) == a。 IAC通过使用中间volatile double代码来防止这种情况发生。

答案 1 :(得分:0)

我不确定你可以在演员之前检查这个转换,但是fenv.h似乎可以帮助你进行后投检查。 FE_INEXACT可以让您检查您刚刚执行的操作是否无法准确存储。 http://www.cplusplus.com/reference/cfenv/FE_INEXACT/