Сколько чисел представимо данным типом

332
27 февраля 2017, 12:38

Как узнать, сколько чисел представимо данным типом, кроме std::pow(2., sizeof(type)*8)?

Answer 1

С++11 std::numeric_limits<type>::max()

Answer 2

не уверен, но можно опробовать так:

unsigned int ui = 0;
int i = (x - 1)/2

вообще вроде в библиотеке limits.h есть INT_MAX

Answer 3

Нашёл:

std::numeric_limits<std::make_unsigned<my_type>::type>::max()

Answer 4

Для целочисленных типов кол-во различных вариантов может быть получено путём вычитания минимально возможного значения из максимально возможного и добавления единицы, т.е.:

std::numeric_limits<T>::max() - std::numeric_limits<T>::min() + 1;

Но здесь стоит учесть тот момент, что для типов с рангом >= int мы получим переполнение и результат в виде нуля. Чтобы этого не произошло нужно привести первый аргумент к некоторому максимально возможному целому типу. Назовём его пока BigInt.

static_cast<BigInt>(std::numeric_limits<T>::max()) - std::numeric_limits<T>::min() + 1;

Этот подход увеличит кол-во типов, для которых можно вызывать код, но переполнение всё равно будет возникать для ситуаций, когда sizeof(T) == sizeof(BigInt). И этого не избежать, т.к. любой тип будет иметь представление для нуля, а стало быть кол-во возможных вариантов как минимум на единицу больше, чем максимально представимое этим типом число.

Для демонстрации в качестве BigInt я выбрал нестандартный, но имеющийся в различных компиляторах тип __int128_t:

template <class T>
auto range() {
    return static_cast<__int128_t>(std::numeric_limits<T>::max()) - std::numeric_limits<T>::min() + 1;
}

Проверка (код для вывода значения типа __int128_t заимствован из ответа James Kanze, т.к. готовых решений компиляторами не предоставляется):

#include <cstdint>
#include <limits>
#include <iostream>
std::ostream&
operator<<( std::ostream& dest, __int128_t value )
{
    std::ostream::sentry s( dest );
    if ( s ) {
        __uint128_t tmp = value < 0 ? -value : value;
        char buffer[ 128 ];
        char* d = std::end( buffer );
        do
        {
            -- d;
            *d = "0123456789"[ tmp % 10 ];
            tmp /= 10;
        } while ( tmp != 0 );
        if ( value < 0 ) {
            -- d;
            *d = '-';
        }
        int len = std::end( buffer ) - d;
        if ( dest.rdbuf()->sputn( d, len ) != len ) {
            dest.setstate( std::ios_base::badbit );
        }
    }
    return dest;
}
template <class T>
auto range() {
    return static_cast<__int128_t>(std::numeric_limits<T>::max()) - std::numeric_limits<T>::min() + 1;
}
int main() {
    std::cout << range<int>() << "\n"
    << range<unsigned>() << "\n"
    << range<long>() << "\n"
    << range<char>() << "\n"
    << range<short>() << "\n"
    << range<unsigned long long>() << "\n"
    << range<bool>() << "\n";
}

Возможный вывод:

4294967296  
4294967296  
18446744073709551616  
256  
65536  
18446744073709551616  
2  

Вариант с std::make_unsigned, предложенный в другом ответе, не будет работать для типа bool, т.к. он не имеет возможности быть знаковым или беззнаковым.

READ ALSO
namespace в dll

namespace в dll

Пишу dll на C++Можно ли помещать в ней функцию в namespace? Если да, то какой в этом профит, кроме решения проблемы неуникальности имен и как вызывать...

261
Именованный канал по сети без логина и пароля

Именованный канал по сети без логина и пароля

Как создать именованный канал в Windows, чтобы можно было читать из него и записывать данные в него без каких-либо логинов и паролей с компьютеров...

289
Балансировка дерева и приведение его к АВЛ сбалансированному дереву

Балансировка дерева и приведение его к АВЛ сбалансированному дереву

В файле записаны числа, нужно их считать, построить дерево поискаПосле этого сбалансировать дерево, выполнив RR поворот

257
end() vs cend()

end() vs cend()

Всегда ли это предложение возвращает true для стандартных контейнеров?

265