Использует водосливную хорошую практику целого числа без знака?

Java, основанная на втором решении Эско:

class C{
    public static void main(String[]d){
        String s="";
        d="first1second1third1fourth1fifth1sixth1seventh1eighth1ninth1tenth1eleventh1twelfth".split("1");
        String[]g="a partridge in a pear tree1two turtle doves,\nand 1three french hens,\n1four calling birds,\n1five gold rings,\n1six geese a-laying\n1seven swans a-swimming,\n1eight maids a-milking,\n1nine ladies dancing,\n1ten lords a-leaping,\n1eleven pipers piping,\n1twelve drummers drumming,\n".split("1");
        for(int i=0;i<12;)
            System.out.println("On the "+d[i]+" day of Christmas my true love gave to me:\n"+
                    (s=g[i++]+s)+".\n");
    }
}

Если я посчитал правильно, то это 579 символов (не считая отступов и переносов). И этот полностью работает и не печатает каждый стих в одной строке. Выходные данные:

В первый день Рождества моя настоящая любовь подарила мне:
куропатку в грушевом дереве.

Во второй день Рождества моя настоящая любовь подарила мне:
двух горлиц и
куропатку в грушевом дереве.

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

...


РЕДАКТИРОВАТЬ: Немного улучшенная версия, основанная на идее Балабастера о замене общей строки одним символом:

class C{
    public static void main(String[]d){
        String s="";
        d="first1second1third1fourth1fifth1sixth1seventh1eighth1ninth1tenth1eleventh1twelfth".split("1");
        String[]g="a partridge in a pear tree1two turtle doves,\nand 1three french hens,\n1four calling birds,\n1five gold rings,\n1six geese a-lay#seven swans a-swimm#eight maids a-milk#nine ladies danc#ten lords a-leap#eleven pipers pip#twelve drummers drumm#".replace("#","ing,\n1").split("1");
        for(int i=0;i<12;)
            System.out.println("On the "+d[i]+" day of Christmas my true love gave to me:\n"+
                (s=g[i++]+s)+".\n");
    }
}

Теперь до 562 символов (хотя я добавил запятую) что я пропустил раньше).

19
задан user122147 12 June 2009 в 19:29
поделиться

11 ответов

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

20
ответ дан 30 November 2019 в 03:53
поделиться

Вкратце:

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

3
ответ дан 30 November 2019 в 03:53
поделиться

То, что вы знаете подробности стандарта, не означает, что это знает человек, поддерживающий ваш код. Этому человеку, возможно, придется тратить время на то, чтобы беспокоиться об этом при отладке позже, или ему придется поискать стандарт, чтобы проверить это поведение позже.

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

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

Короче говоря,

3
ответ дан 30 November 2019 в 03:53
поделиться

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

Практические советы по целочисленному переполнению :
http://www.gnu.org/software/hello/manual/autoconf/Integer-Overflow-Basics.html#Integer-Overflow-Basics.html#Integer-Overflow-Basics

3
ответ дан 30 November 2019 в 03:53
поделиться

Поскольку числа со знаком на ЦП могут быть представлены по-разному, 99,999% всех текущих ЦП используют нотацию с дополнением до двух. Поскольку это большинство машин, трудно найти другое поведение, хотя компилятор может это проверить (большой шанс). Спецификации C, однако, должны составлять 100% компиляторов, поэтому не определили его поведение.

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

0
ответ дан 30 November 2019 в 03:53
поделиться

I wouldn't rely on it just for readability reasons. You're going to be debugging your code for hours before you figure out where you're resetting that variable to 0.

1
ответ дан 30 November 2019 в 03:53
поделиться

Еще одно место, где можно с пользой использовать беззнаковое переполнение, - это когда вам нужно выполнить итерацию назад от заданного беззнакового типа:

void DownFrom( unsigned n )
{
    unsigned m;

    for( m = n; m != (unsigned)-1; --m )
    {
        DoSomething( m );
    }
}

Другие альтернативы не так удобны. Попытка выполнить m> = 0 не сработает, если вы не измените m на знаковое, но тогда вы можете усечь значение n или, что еще хуже, преобразовать его в отрицательное число при инициализации.

В противном случае вам нужно сделать! = 0 или> 0, а затем вручную выполнить регистр 0 после цикла.

1
ответ дан 30 November 2019 в 03:53
поделиться

Я все время использую его, чтобы сказать, пора ли что-то делать.

UInt32 now = GetCurrentTime()

if( now - then > 100 )
{
   // do something
}

Пока вы проверяете значение до «сейчас, кругов, потом», все в порядке. значения «сейчас» и «тогда».

РЕДАКТИРОВАТЬ: Я предполагаю, что это действительно потеря значимости.

2
ответ дан 30 November 2019 в 03:53
поделиться

Можно полагаться на переполнение, если вы знаете, КОГДА оно произойдет ...

Я, например, имел проблемы с реализацией C MD5 при переходе на более свежий компилятор ... Код действительно ожидал переполнения, но он также ожидал 32-битных int.

С 64-битными результатами были неправильные!

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

Вы можете возразить, «но такое случается редко»: да, но это делает это еще более опасным! Когда возникает ошибка, все с подозрением относятся к коду, написанному за последние несколько дней. Никто не вызывает подозрений в отношении кода, который «просто работал годами» и обычно никто до сих пор не знает, как он работает ...

0
ответ дан 30 November 2019 в 03:53
поделиться

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

0
ответ дан 30 November 2019 в 03:53
поделиться

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

0
ответ дан 30 November 2019 в 03:53
поделиться