Как вычислить максимальное значение перемменой типа unsigned long. (С)

Модератор: Модераторы разделов

gKOSS
Сообщения: 9
ОС: Gentoo ~amd64

Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение gKOSS »

Ну раз уж есть раздел для начинающих то задам и я свой (возможно для кого то) глупый вопрос.
Хотелось бы узнать быстрый способ вычисления максимального значения переменной типа unsigned long. Именно вычислить, а не взять значение из limits.h.
Спасибо сказали:
Аватара пользователя
sirocco
Сообщения: 782
Статус: Задвинутый соучастник

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение sirocco »

sizeof()
не подойдёт?
Спасибо сказали:
ivze
Сообщения: 39
ОС: Ubuntu

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение ivze »

sirocco писал(а):
14.12.2009 16:55
sizeof()
не подойдёт?

Можно какое-нибудь там

Код: Выделить всё

....
unsigned long max=0;
max-=1;
...

Оно перескочит на максимальное значение.
Главный вопрос: зачем оно вам? 8)
Спасибо сказали:
strephil
Сообщения: 47
ОС: GNU

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение strephil »

не будет ли ответом это:
unsigned long i = -1

нужно внимательно посмотреть, что в Стандартах говорится о представлении целых чисел…
Спасибо сказали:
strephil
Сообщения: 47
ОС: GNU

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение strephil »

Проверил, да unsigned long max = -1 это стандартно.
это преобразование unsigned в signed уже зависит от реализации.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение drBatty »

gKOSS писал(а):
14.12.2009 16:14
Хотелось бы узнать быстрый способ вычисления максимального значения переменной типа unsigned long

Код: Выделить всё

unsigned long max = ~0;
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
gKOSS
Сообщения: 9
ОС: Gentoo ~amd64

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение gKOSS »

Можно какое-нибудь там

Код: Выделить всё

....
unsigned long max=0;
max-=1;
...

Оно перескочит на максимальное значение.

Спс, я думал что не перескочит, а оказывается перескакивает.
Главный вопрос: зачем оно вам? 8)

Такие вот задачки у Кернигана.

Код: Выделить всё

unsigned long max = ~0;

Что означает ~ в данном случае?
Спасибо всем за ответы, но возник другой вопрос: как тогда вычислить min и max у signed long ?
Спасибо сказали:
ivze
Сообщения: 39
ОС: Ubuntu

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение ivze »

~ - это такая штука, которая инвертирует все биты.

Код: Выделить всё

long allbits = ~((long)0); /* 11111...111 */
long max = allbits >> 1;/* 01111...111*/
long min = max + 1; /* 10000....000 */

Если я где-то не ошибся, для типов со знаками это делается так.
Спасибо сказали:
gKOSS
Сообщения: 9
ОС: Gentoo ~amd64

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение gKOSS »

ivze писал(а):
14.12.2009 20:22
~ - это такая штука, которая инвертирует все биты.

Код: Выделить всё

long allbits = ~((long)0); /* 11111...111 */
long max = allbits >> 1;/* 01111...111*/
long min = max + 1; /* 10000....000 */

Если я где-то не ошибся, для типов со знаками это делается так.


Видимо ошиблись, тк при таком раскладе min = 0 max = -1 :(
Спасибо сказали:
strephil
Сообщения: 47
ОС: GNU

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение strephil »

ivze,
отрицательные числа могут быть представлены не только в дополнительном коде, это зависит от реализации…

long min = max + 1; /* 10000....000 */

поэтому, полагаю, такое вот выражение решением задачи счтиаться не может.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение NickLion »

drBatty писал(а):
14.12.2009 18:47

Код: Выделить всё

unsigned long max = ~0;

В принципе, это то же самое, что и -1. Разницы абсолютно никакой (в данном случае).

Диапазон для signed можно определить сдвигом вправо на 1 но, вот для беззнакового типа (иначе размножение знака будет работать).

Код: Выделить всё

    unsigned long long maxu = ~0; // тут спасает размножение знака
    signed long long maxs = maxu >> 1; // тут как раз оно не работает, что хорошо
    signed long long mins = maxs + 1;
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение drBatty »

NickLion писал(а):
15.12.2009 00:23
В принципе, это то же самое, что и -1. Разницы абсолютно никакой (в данном случае).

зависит от железа. запись ~0 более безопасна (хотя тоже...)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение NickLion »

drBatty писал(а):
15.12.2009 00:43
запись ~0 более безопасна (хотя тоже...)

Не более... 0 - это тип int, значит ~0 - тоже int (-1), может быть и меньше, чем результирующий... но спасет дублирование знакового бита.
Спасибо сказали:
Аватара пользователя
Crazy
Сообщения: 862
Статус: Адепт Дзен.
ОС: Mint, Win7.

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение Crazy »

Если не нравится 0

Код: Выделить всё

unsigned long max = ~0;

то можно так.

Код: Выделить всё

max=max^max;
max=~max;


отрицательные числа могут быть представлены не только в дополнительном коде, это зависит от реализации…

И где сейчас реализовано не в доп. коде?

Desipere in loco
Спасибо сказали:
strephil
Сообщения: 47
ОС: GNU

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение strephil »

drBatty писал(а):
15.12.2009 00:43
NickLion писал(а):
15.12.2009 00:23
В принципе, это то же самое, что и -1. Разницы абсолютно никакой (в данном случае).

зависит от железа. запись ~0 более безопасна (хотя тоже...)


От железа это не зависит.

Целое беззнаковое число представлено наобром бит, каждый из которых выражает соответсвтующую степень двойки. Таким образом могут быть представлены числа от 0 до 2^N - 1, где N — число битов. ~0 может соответствовать только 2^N - 1 и ничему другому. Это максимальное беззнаковое целое в любой реализации C на любом железе.

Преобразование отрицательного знакового целого в целое беззнаковое тоже стандартная операция. Если преобразуемое число не может быть выражено новым типом, к нему будет прибавляться (или из него вычитаться) 2^N до тех пор, пока оно не попадёт в диапазон представимых значений.
В нашем случае, мы преобразуем непредставимое беззнаковым целым число -1. Чтобы оно попало в представимый диапазн значений, достаточно прибавить к нему 2^N один раз. Получаем то самое 2^N - 1
Это не зависит от способа представления знаковых чисел/железа. Описано в стандартах.

Crazy писал(а):
15.12.2009 01:55
отрицательные числа могут быть представлены не только в дополнительном коде, это зависит от реализации…

И где сейчас реализовано не в доп. коде?

какая разница, где это реализовано сейчас?
даже если сегодня таких реализаций и нет (хотя я и сомневаюсь, что вообще нет), такие реализации могут появиться в любой момент.

вы же не собираетесь переписывать свой код всякий раз, когда сменяется способ представления отрицательных целых?
Спасибо сказали:
gKOSS
Сообщения: 9
ОС: Gentoo ~amd64

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение gKOSS »

NickLion писал(а):
15.12.2009 00:23

Код: Выделить всё

    unsigned long long maxu = ~0; // тут спасает размножение знака
    signed long long maxs = maxu >> 1; // тут как раз оно не работает, что хорошо
    signed long long mins = maxs + 1;

Спасибо конечно, но есть ли другой способ боллее понятный для новичка?
У Кернигана и Ритчи эта задача во второй главе "Типы, операторы и выражения", читателю ещё не известны такие операции как побитовое отрицание или сдвиг.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение drBatty »

gKOSS писал(а):
15.12.2009 09:45
Спасибо конечно, но есть ли другой способ боллее понятный для новичка?

вместе с компилятором поставляются хидеры с разными MAXINT и прочими константами. Только они везде называются по разному...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
gKOSS
Сообщения: 9
ОС: Gentoo ~amd64

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение gKOSS »

drBatty писал(а):
15.12.2009 11:09
вместе с компилятором поставляются хидеры с разными MAXINT и прочими константами. Только они везде называются по разному...


Да я в курсе, не сочтите за привереду, но задача изначально была вычислить значение, а не взять из limits.h.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение drBatty »

gKOSS писал(а):
15.12.2009 11:40
Да я в курсе, не сочтите за привереду, но задача изначально была вычислить значение, а не взять из limits.h.

ок. просто я подумал, что не все об этом знают.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
ivze
Сообщения: 39
ОС: Ubuntu

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение ivze »

gKOSS писал(а):
14.12.2009 21:27
Видимо ошиблись, тк при таком раскладе min = 0 max = -1 :(



При побитовом сдвиге вправо типов со знаком левый бит размножается. При побитовом сдвиге вправо беззнаковых типов левые биты заполняются нулями. Вот и узнал сам :)!
Мой метод можно исправить, получится так.

Код: Выделить всё

#include<stdio.h>


int main(int argc, char**argv){
    long allbits = ~((long)0); /* 11111...111 */
    long max = ((unsigned long)allbits) >> 1;/* 01111...111*/
    long min = max + 1; /* 10000....000 */
    printf("max=%ld,min=%ld\n", max, min);
    return 0;
}



P.S. Кстати, а где внутренний формат хранения чисел не такой, какой я предполагал в этом примере?
Спасибо сказали:
gKOSS
Сообщения: 9
ОС: Gentoo ~amd64

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение gKOSS »

ivze писал(а):
15.12.2009 14:21
P.S. Кстати, а где внутренний формат хранения чисел не такой, какой я предполагал в этом примере?


В числах с плавающей запятой.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение NickLion »

gKOSS писал(а):
15.12.2009 09:45
Спасибо конечно, но есть ли другой способ боллее понятный для новичка?
У Кернигана и Ритчи эта задача во второй главе "Типы, операторы и выражения", читателю ещё не известны такие операции как побитовое отрицание или сдвиг.

Думал нужен самый эффективный код. Если простой, то вот:

Код: Выделить всё

unsigned long maxu = 0;
for( unsigned long i = 1; i; i *= 2 ) maxu += i;
// maxu = -1; как вариант, тоже что и ~0
long maxs = 0;
for( long i = 1; i > 0; i *= 2 ) maxs += i;
long mins;
for( long i = -1; i < 0; i *= 2 ) mins = i;
Спасибо сказали:
strephil
Сообщения: 47
ОС: GNU

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение strephil »

ivze писал(а):
15.12.2009 14:21
P.S. Кстати, а где внутренний формат хранения чисел не такой, какой я предполагал в этом примере?

Например, машины PDP-1, CDC 160A, UNIVAC 1100/2200, как утверждает Википедия, использовали метод дополнения до единицы для внутреннего представления целых со знаком.
Спасибо сказали:
gKOSS
Сообщения: 9
ОС: Gentoo ~amd64

Re: Как вычислить максимальное значение перемменой типа unsigned long.

Сообщение gKOSS »

NickLion писал(а):
15.12.2009 16:35

Код: Выделить всё

unsigned long maxu = 0;
for( unsigned long i = 1; i; i *= 2 ) maxu += i;
// maxu = -1; как вариант, тоже что и ~0
long maxs = 0;
for( long i = 1; i > 0; i *= 2 ) maxs += i;
long mins;
for( long i = -1; i < 0; i *= 2 ) mins = i;


Спасибо, то что надо!
Спасибо сказали: