确定值是否在c ++中该数据类型的最大范围内

时间:2018-04-07 16:09:17

标签: c++ c++11

确定一个数字(在我的情况下,它是由if(pow (2,128)>std::numeric_limits<float>::max())计算的2的幂的值)是否在一个变量类型可以采用的值范围内的正确方法是什么?我这样做:true,但这被评估为v.GetType(),尽管预计浮动的最大值是2 ^ 128或更多。有没有更好的方法来进行这种比较?

3 个答案:

答案 0 :(得分:2)

您可以取变量类型的最大限制的基数2对数,并将其与n进行比较。例如:if(n > std::log2(std::numeric_limits<float>::max())。你可能不希望n完全符合限制,因为我认为像浮点错误之类的东西可能会导致一些问题,这就是为什么你的例子不起作用,即使限制正好是2 ^ 128。

答案 1 :(得分:1)

对于这些类型的限制检查,您可以移动这些术语以保持在类型的限制范围内。

在这种情况下,pow(2,n) == exp(ln(2)*n)在数学上,因此,重新排列术语,您可以使用n > ln(maxval)/ln(2)

答案 2 :(得分:-2)

首先,您能回答pow(2, 128)的结果吗? 真正的问题是这个表达的类型是什么?

第二个问题是你知道浮点数是如何工作的吗?

看看这段代码,给你一个提示:

#include <cmath>
#include <iostream>
#include <limits>

template<class T>
void printInfo(const std::string& desc, T x)
{
    std::cout << desc << ' ' << typeid(x).name() << ' ' << x << std::endl;
}

int main()
{
    printInfo("A", std::pow(2, 128));
    printInfo("B", std::pow(2.0f, 128));
    printInfo("A", std::pow(2, 128.0f));
    auto c = std::pow(2.0f, 128.0f);
    printInfo("C", c);

    std::cout << (c > std::numeric_limits<float>::max()) << std::endl;
    std::cout << (c == std::numeric_limits<float>::infinity()) << std::endl;

    return 0;
}

https://wandbox.org/permlink/bHdKqToDKdC0hSvW

我建议审核numeric_limits的文档。 并分析此代码:

#include <cmath>
#include <iostream>
#include <limits>

template<class T>
void print2exp()
{
    std::cout << typeid(T).name() << '\n';
    std::cout << "Radix          = " << std::numeric_limits<T>::radix << '\n';
    auto maxExp = std::numeric_limits<T>::max_exponent;
    std::cout << "Max exp        = " << maxExp  << '\n';
    std::cout << "2^maxExp       = " << std::pow(static_cast<T>(2), static_cast<T>(maxExp)) << '\n';
    std::cout << "2^(maxExp - 1) = " << std::pow(static_cast<T>(2), static_cast<T>(maxExp - 1)) << '\n';
}

int main()
{
    print2exp<float>();
    print2exp<double>();
    print2exp<long double>();

    return 0;
}

https://wandbox.org/permlink/J0hACKUKvKlV8lYK

对此的正确方法是(假设基数为2):

if (x < std::numeric_limits<T>::max_exponent) {
    return std::pow(static_cast<T>(2), static_cast<T>(x));
} else {
    throw invalid_argument("x is to big to be use as 2^x");
}