?

Log in

No account? Create an account

Программистское - Ваши рубидии уже у кобальта во ртути

May. 30th, 2013

08:10 pm - Программистское

Previous Entry Share Next Entry

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

В некоторых языках программирования есть понятие контейнера. Это такой черный ящик, в котором лежат вещи. У контейнера обычно можно спросить, сколько вещей в нем лежит, и ответом будет натуральное число, т. е. целое число без знака: ноль или больше.

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

Иногда возникает необходимость выяснить, все ли вещи в контейнере одинаковые/похожие. Для этого логично сравнить количество вещей в контейнере с количеством вещей, равных/похожих на первую из них.

И тут в кое-каком языке программирования возникает неувязочка. По причинам теоретически-исторического характера функция, считающая, сколько в контейнере вещей, похожих на данную, возвращает не натуральное число, а целое со знаком, которое, конечно же, никогда не меньше нуля, но компилятор этого не знает и предупреждает при сравнении всё равно. Нормальные программисты на это предупреждение, конечно же, забивают, но люди, заведующие тем, чтобы всё было аккуратненько, хотят, чтобы предупреждений от компилятора не было совсем.

Сколько человеко-лет было убито на разбирательства, почему это так - бог весть; я не удивлюсь, если это суммарное время окажется больше, чем суммарный возраст всех членов комитета по стандартизации этого языка.



Если они штатские такие умные, почему не придумали iterator trait для абсолютного значения разницы между двумя итераторами? Суки злобные.

Comments:

[User Picture]
From:yatur
Date:May 31st, 2013 04:21 am (UTC)
(Link)
Мелочи это. Неудобства на уровне отсутствия точек над буквой ё.

Нормального математика, скажем, должен хватить Кондратий, когда он узнает, что x=x+1 - истина для всех значений x кроме -1. Я уж не говорю о том, что в некоторых языках программирования 2/3 == 0.
(Reply) (Thread)
[User Picture]
From:spamsink
Date:May 31st, 2013 04:28 am (UTC)
(Link)
Понятно, что неудобство невеликое, но зачем делать неудобно, если можно было сделать удобно?

Нормальный математик при виде х=х+1 должен немедленно спросить, в том же ли смысле в данном случае используется знак =, что и в математике. Да и о целочисленном делении математики вроде бы в курсе.
(Reply) (Parent) (Thread)
[User Picture]
From:yatur
Date:May 31st, 2013 11:20 am (UTC)
(Link)
> при виде х=х+1 должен немедленно спросить, в том же ли смысле в данном случае используется знак =

Ну да, это же С++. Там не только знак = может использоваться не в том смысле, но и +, и 1 и даже х.

class MyClass ...
{
MyClass(int);
operator =;
operator +;
}

MyClass x(42);

x=x+1;
(Reply) (Parent) (Thread)
[User Picture]
From:dvv
Date:May 31st, 2013 02:53 pm (UTC)
(Link)
Сдуру можно и хуй сломать. (Лёня, честное слово — ломание хуя как вид искусства (обфускаторские контесты) вызывают у меня только уважение.)
(Reply) (Parent) (Thread) (Expand)
[User Picture]
From:fatoff
Date:May 31st, 2013 04:30 am (UTC)
(Link)
> Why is the return type of std::count a ptrdiff_t?
> iterator_traits::difference_type according to my documentation

Похоже, кто-то очень ленив. Они количество элементов выводили через разницу адресов поделённую на размер элемента. Похоже, внутри стандартной библиотеки кому-то не хотелось заморачиваться кастнигом к size_t, со всеми нежелательными моментами. По крайней мере, раз STL алгоритмы могут работать и со старыми сишными массивами, там это точно так. Вот и выдали наружу difference_type, пусть пользователи STL будут тем довольны.

(Reply) (Thread)
[User Picture]
From:spamsink
Date:May 31st, 2013 06:06 am (UTC)
(Link)
Объяснение там такое, что раз считаем от итератора до итератора, то сумма может быть того же порядка - и, соответственно, целого типа, - что и разница между итераторами (формально, больше чем size_t - например, какой-нибудь BigInt), а беззнакового аналога для целей cardinality в iterator_traits сдуру не предусмотрели, а теперь уже поздно.
(Reply) (Parent) (Thread)
[User Picture]
From:archaicos
Date:May 31st, 2013 06:29 am (UTC)
(Link)
А всё из-за того, что покойный Dennis Ritchie поленился заложить в язык нормальное математическое сравнение целых со знаком с целыми без знака. Думаю, компилятор не перестал бы влезать в память с такой маленькой, но весьма полезной feature'й, в отсутствие которой люди продолжают биться головой третий или даже уже четвёртый десяток лет.

Я был удивлён тому, что в Go весьма учтиво расстелили похожие грабли. Нижеследующий код не компилируется:
    var ui32 uint32 = 1
    var i32 int32 = -1
 
    if ui32 > i32 {
        fmt.Println("(uint32)1 > (int32)-1")
    } else {
        fmt.Println("(uint32)1 <= (int32)-1")
    }

Ошибка: invalid operation: ui32 > i32 (mismatched types uint32 and int32)

В результате человек вынужден ручками делать приведение типов чтобы сравнить два таких целых. И он может сделать это сравнение неправильно если по простоте душевной напишет
    if ui32 > uint32(i32) {

или
    if int32(ui32) > i32 {


А так тоже не компилируется, то же несоответствие типов:
    if int64(ui32) > i32 {


Но зато можно так:
    if int64(ui32) > int64(i32) {


Похоже, и в Google' не дураки сидят.
(Reply) (Thread)
[User Picture]
From:spamsink
Date:May 31st, 2013 07:06 am (UTC)
(Link)
А всё из-за того, что покойный Dennis Ritchie поленился

Ответ неправильный. Всё из-за того, что в системе команд PDP-11 не было команды сравнения числа со знаком с числом без знака.
(Reply) (Parent) (Thread)
[User Picture]
From:archaicos
Date:May 31st, 2013 07:13 am (UTC)
(Link)
Было-не было — какая разница? Вон, 64-х-битный тип не всеми процессорами поддерживается сейчас, как 32-х-битный раньше, и ничего, пишут подпрограммы длинного умножения и деления для компилятора под такой процессор. Никто не умирает от непосильности задачи.
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:May 31st, 2013 07:32 am (UTC)
(Link)
В оригинальном С многое делалось подпрограммами (в первую очередь csv/cret), но идея, что два побитово идентичных целых числа могут быть неравны, видимо, в голову не приходила, т.е. это не лень (в ранних Си ради экономии размера объектного кода были операторы max и min, записываемые как \/ и /\), и даже не недосмотр, а несоответствие идеи тогдашнему духу языка.

(Reply) (Parent) (Thread) (Expand)
[User Picture]
From:b0p0h0k
Date:May 31st, 2013 07:57 am (UTC)
(Link)
Может оно несколько OT, но всё равно. Понравилось в недавних job requirements:
...
- Strong background in C and enough understanding of C++ to know to stay away from it.
...
(Reply) (Thread)
[User Picture]
From:spamsink
Date:May 31st, 2013 08:08 am (UTC)
(Link)
Видать, работа была не для алгоритмистов. Точнее было бы сказать "... to know to stay away from it for tasks executed in the offered position".
(Reply) (Parent) (Thread)
[User Picture]
From:archaicos
Date:May 31st, 2013 08:39 am (UTC)
(Link)
Голый C на порядок-полтора проще и понятней его же но со всеми плюсами. Уже 10 лет работаю над проектами, где С++ используют очень осторожно и аккуратно (=минимально) чтобы поменьше сюрпризов было от непонимания языка и особенностей компилятора.
(Reply) (Parent) (Thread)
[User Picture]
From:yatur
Date:May 31st, 2013 11:18 am (UTC)
(Link)
> Голый C на порядок-полтора проще и понятней его же но со всеми плюсами

+= MAX_INT :)
(Reply) (Parent) (Thread) (Expand)
[User Picture]
From:boris71
Date:June 3rd, 2013 04:18 am (UTC)
(Link)
Было убито некоторое несомненно неотрицательное число человеко-лет. Но функция, которая это рассчитывает, будучи написана на том же самом языке программирования, по тем же самым причиным выдает результат целого типа со знаком...

Невезуха тебе, Леня.
(Reply) (Thread)