微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 查找浮点类型可以处理的最大整数大小而不会丢失精度

Double的范围超过64位整数,但其精度不如其表示(因为double也是64位,它不能适合更多的实际值).因此,当表示较大的整数时,您开始在整数部分中失去精度.
#include <boost/cstdint.hpp>
#include <limits>

template<typename T,typename TFloat>
void
maxint_to_double()
{
    T i = std::numeric_limits<T>::max();
    TFloat d = i;
    std::cout
        << std::fixed
        << i << std::endl
        << d << std::endl;
}

int
main()
{
    maxint_to_double<int,double>();
    maxint_to_double<boost::intmax_t,double>();
    maxint_to_double<int,float>();
    return 0;
}

这打印:

2147483647
2147483647.000000
9223372036854775807
9223372036854775800.000000
2147483647
2147483648.000000

注意max int如何在不损失精度的情况下适合双精度而boost :: intmax_t(在这种情况下为64位)不能. float甚至不能持有int.

现在,问题是:在C中是否有一种方法可以检查给定整数类型的整个范围是否可以适应一个浮动点类型而不会损失精度?

最好,

>这将是一个可以在静态断言中使用的编译时检查,
>并且不会涉及枚举编译器应该知道或可以计算的常量.

解决方法

只是一个小谓词:
#include <limits>

template <typename T,typename U>
struct can_fit
{
    static const bool value = std::numeric_limits<T>::digits
                            <= std::numeric_limits<U>::digits;
};

#include <iostream>

int main(void)
{
    std::cout << std::boolalpha;

    std::cout << can_fit<short,float>::value << std::endl;
    std::cout << can_fit<int,float>::value << std::endl;

    std::cout << can_fit<int,double>::value << std::endl;
    std::cout << can_fit<long long,double>::value << std::endl;

    std::cout << can_fit<short,int>::value << std::endl;
    std::cout << can_fit<int,short>::value << std::endl;
}

测试一个T中可用的二进制精度是否存在于U.适用于所有类型.

“Boostified”:

// this is just stuff I use
#include <boost/type_traits/integral_constant.hpp>

template <bool B>
struct bool_type : boost::integral_constant<bool,B>
{
    static const bool value = B;
};

typedef const boost::true_type& true_tag;
typedef const boost::false_type& false_tag;

// can_fit type traits
#include <limits>

namespace detail
{
    template <typename T,typename U>
    struct can_fit
    {
        static const bool value = std::numeric_limits<T>::digits
                                <= std::numeric_limits<U>::digits;
    };
}

template <typename T,typename U>
struct can_fit : bool_type<detail::can_fit<T,U>::value>
{
    typedef T type1;
    typedef U type2;

    static const bool value = detail::can_fit<T,U>::value;
};

// test
#include <iostream>

namespace detail
{
    void foo(true_tag)
    {
        std::cout << "T fits in U" << std::endl;
    }

    void foo(false_tag)
    {
        std::cout << "T does not fit in U" << std::endl;
    }
}

// just an example
template <typename T,typename U>
void foo(void)
{
    detail::foo(can_fit<T,U>());
}

int main(void)
{
    foo<int,double>();
}

原文地址:https://www.jb51.cc/c/110808.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐