-1

我必须将一个整数值乘以 2^31。我用谷歌搜索了它,看起来双打的范围在 2.23e-308 <= |X| 之间 <= 1.79e308 使用 64 位,浮点数介于 1.18e-38 <= |X| <= 3.40e38。

这比我需要的要多得多。但它不起作用。

我的头文件中有这个常量值:

static const float SCALE_FACTOR = 2^-31;

如果那时我只是这样做:

float dummy = SCALE_FACTOR;

那么,dummy 的值为 11。

我不知道问题是否在于分配这样的常量值,但我不知道如何在不丢失精度的情况下编写它。

有什么帮助吗?

编辑:对不起,愚蠢的问题。我的 MatLab 背景背叛了我,忘记了 ^ 不适用于 C++ 中的求幂。我已经投票关闭。

4

4 回答 4

4

^ 是 C++ 中的按位异或运算符,而不是数学求幂运算符。你有几个选择。

  1. 因为您以本质上有损格式 a 存储常量,所以float您可以计算出 base-10e形式的文字并使用它:也许类似于4.6566128730773926e-0102^-31。这很容易出错(例如,我已经做了一个),并且不一定可以在浮点格式之间移植。
  2. 您可以使用可以在编译时计算的常量表达式来设置常量,并使用整数文字:例如2^310x80000000或2^-311UL << 311.0f / 0x800000002^-31。

当然,您可以使用某种pow函数在运行时计算值。

顺便说一句,如果您使用整数,为什么不直接使用long long或其他 64 位整数类型,而不是可能会出现舍入错误的浮点数?从您的问题来看,您是否正在查看浮点值并不完全清楚,因为您需要浮点值范围,还是因为您只是担心溢出 32 位整数值。

于 2012-11-14T12:38:04.170 回答
1

在您的代码中

static const float SCALE_FACTOR = 2^-31;

static多余的(常量默认有内部链接),^表示按位异或,-没有意义(至少如果你想“乘以 2^31”),并且float是不必要的特殊选择,而不是默认浮点类型double(例如是浮点文字的类型,例如3.14)。

此外,在 C++ 中保留为宏大写所有大写标识符(通用约定)。将它们用于常量是一种 Java 主义。具有讽刺意味的是,Java 约定起源于 C,过去的常量有时必须表示为宏。

相反,因此写

double const scale_factor = 1uL << 31;

在哪里

  • 没有明确指定内部链接(关键字static),

  • 使用默认浮点类型double而不是float,

  • 不使用全大写标识符(应为宏保留),

  • 使用左位移<<来计算二的幂,而不是不正确的^

  • 不添加任何无意义的减号,

  • 使用类型unsigned long(由 指定uL)确保有足够的范围。

于 2012-11-14T12:50:39.100 回答
0

^是按位 XOR 的运算符,而不是用于提高幂的运算符。你需要std::pow().

于 2012-11-14T12:37:05.873 回答
0

乘以 2 的幂相当于左移该幂。要将整数乘以 2 到 31,只需将其移位:

unsigned long value = whatever;
unsigned long value_times_2_to_the_31 = value << 31;

这里不需要浮点数学。但为了完整起见,要产生 2 到 31 的双精度值:

double two_to_the_31 = std::ldexp(1.0, 31);

请注意,虽然在某些情况下,带符号类型的移位表达式的结果在形式上是未定义的,但这是由于整数类型溢出造成的;使用浮点数学并不能消除溢出,它只是将其放入代码的不同部分。

于 2012-11-14T13:30:41.563 回答