我的问题是如何将size_t转换为double或int C++
我有一个size_t数据,但现在我想将其转换为double或int。
如果我这样做
size_t data = 99999999;
int convertdata = data;
编译器会报告警告。因为它可能溢出。
你有一些像boost或其他方法来做转换的方法吗?
我的问题是如何将size_t转换为double或int C++
我有一个size_t数据,但现在我想将其转换为double或int。
如果我这样做
size_t data = 99999999;
int convertdata = data;
编译器会报告警告。因为它可能溢出。
你有一些像boost或其他方法来做转换的方法吗?
打石膏,as Blaz Bratanic suggested:
size_t data = 99999999;
int convertdata = static_cast<int>(data);
可能沉默警告(虽然原则上编译器警告任何它喜欢的,即使有一个投)。
但它不能解决警告告诉你的问题,即从size_t
到int
的转换确实会溢出。
如果可能的话,设计程序让你不需要到size_t
值转换为int
。只需将其存储在size_t
变量中(如您已经完成的那样)并使用它。
转换为double
不会导致溢出,但可能会导致非常大的值的精度下降。同样,将size_t
转换为double
也没什么意义;你仍然最好保持size_t
变量的值。
静态浇铸:
static_cast<int>(data);
如果您的代码已准备好处理溢出错误,那么如果data
太大,则可以抛出异常。
size_t data = 99999999;
if (data > INT_MAX)
{
throw std::overflow_error("data is larger than INT_MAX);
}
int convertData = static_cast<int>(data);
您可以使用Boost numeric_cast
。
如果源值超出目标类型的范围,则会引发异常,但在转换为double
时,它不会检测到精度损失。
不管你使用什么功能,你应该决定在size_t
的值大于INT_MAX
的情况下你想要发生什么。如果你想检测它使用numeric_cast
或写你自己的代码来检查。如果您知道它不可能发生,那么您可以使用static_cast
来抑制警告,而不需要运行时检查的代价,但是在大多数情况下,成本无关紧要。
如果你不能避免这种转换,但是希望程序让你知道是否发生out_of_range,那么需要什么。 – Arkady
假设程序不能被重新设计,以避免铸(REF Keith Thomson's answer):
要已从size_t强制转换为int,你需要确保的size_t不超过INT的最大值。这可以通过使用std::numeric_limits来完成:
int SizeTToInt(size_t data)
{
if (data > std::numeric_limits<int>::max())
throw std::exception("Invalid cast.");
return std::static_cast<int>(data);
}
如果需要已从size_t加倍投,你需要确保你不会失去精度,我想你可以使用窄铸(REF斯特劳斯:在C++编程语言,第四版):
template<class Target, class Source>
Target NarrowCast(Source v)
{
auto r = static_cast<Target>(v);
if (static_cast<Source>(r) != v)
throw RuntimeError("Narrow cast failed.");
return r;
}
我通过检查最大整数浮点表示的整数的范围(代码使用googletest)使用用于为size_t到双重转换窄铸测试:
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() - 2 })), size_t{ IntegerRepresentableBoundary() - 2 });
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() - 1 })), size_t{ IntegerRepresentableBoundary() - 1 });
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() })), size_t{ IntegerRepresentableBoundary() });
EXPECT_THROW(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 1 }), std::exception);
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 2 })), size_t{ IntegerRepresentableBoundary() + 2 });
EXPECT_THROW(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 3 }), std::exception);
EXPECT_EQ(static_cast<size_t>(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 4 })), size_t{ IntegerRepresentableBoundary() + 4 });
EXPECT_THROW(NarrowCast<double>(size_t{ IntegerRepresentableBoundary() + 5 }), std::exception);
其中
constexpr size_t IntegerRepresentableBoundary()
{
static_assert(std::numeric_limits<double>::radix == 2, "Method only valid for binary floating point format.");
return size_t{2} << (std::numeric_limits<double>::digits - 1);
}
即,如果N是在尾数位的数目,双打小于或等于2^N,整数可以准确地表示。对于2^N和2 ^(N + 1)之间的双打,可以精确地表示每个其他整数。对于2 ^(N + 1)和2 ^(N + 2)之间的双打,每个第四个整数都可以精确表示,依此类推。
*为什么*你想这样做? – crashmstr
@crashmstr - 我不是op,但我需要将size_t传递给C函数。 – ruipacheco
@lapinrigolo然后看看下面的答案...? – crashmstr