2014-03-04 50 views
21

我的问题是如何将size_t转换为double或int C++

我有一个size_t数据,但现在我想将其转换为double或int。

如果我这样做

size_t data = 99999999; 
int convertdata = data; 

编译器会报告警告。因为它可能溢出。

你有一些像boost或其他方法来做转换的方法吗?

+1

*为什么*你想这样做? – crashmstr

+7

@crashmstr - 我不是op,但我需要将size_t传递给C函数。 – ruipacheco

+0

@lapinrigolo然后看看下面的答案...? – crashmstr

回答

29

打石膏,as Blaz Bratanic suggested

size_t data = 99999999; 
int convertdata = static_cast<int>(data); 

可能沉默警告(虽然原则上编译器警告任何它喜欢的,即使有一个投)。

但它不能解决警告告诉你的问题,即从size_tint的转换确实会溢出。

如果可能的话,设计程序让你不需要size_t值转换为int。只需将其存储在size_t变量中(如您已经完成的那样)并使用它。

转换为double不会导致溢出,但可能会导致非常大的值的精度下降。同样,将size_t转换为double也没什么意义;你仍然最好保持size_t变量的值。

11

静态浇铸:

static_cast<int>(data); 
+0

简而言之,正如... –

+1

是否有可能导致溢出,因为size_t的范围大于int的范围。 – user2701639

+1

@ user2701639那么,你想在这种情况下发生什么? –

5

如果您的代码已准备好处理溢出错误,那么如果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); 
8

您可以使用Boost numeric_cast

如果源值超出目标类型的范围,则会引发异常,但在转换为double时,它不会检测到精度损失。

不管你使用什么功能,你应该决定在size_t的值大于INT_MAX的情况下你想要发生什么。如果你想检测它使用numeric_cast或写你自己的代码来检查。如果您知道它不可能发生,那么您可以使用static_cast来抑制警告,而不需要运行时检查的代价,但是在大多数情况下,成本无关紧要。

+1

如果你不能避免这种转换,但是希望程序让你知道是否发生out_of_range,那么需要什么。 – Arkady

1

假设程序不能被重新设计,以避免铸(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)之间的双打,每个第四个整数都可以精确表示,依此类推。