Блог пользователя nicky_ua

Автор nicky_ua, история, 9 лет назад, По-русски

Добрый вечер! Решал одну задачу, наткнулся на такую ошибку:

ll n;
cin >> n;
ll fn = n;
......
ll a = n * (n + 1);
ll b = 10000000000000 * n ;
ll c = n * n;
if (n != fn)
{
	printf("ERROR!!");
}
if (n < 0)
{
	printf("ERROR!!");
}
if (a < 0)
{
	printf("ERROR!!");
}
if (b < 0)
{
	printf("ERROR!!");
}
if (c < 0)
{
	printf("ERROR!!");
}

Опытным путем установил, что в первый if никогда не попадает программа, а во второй попадает. С чем это может быть связано? Переменная fn встречается 2 раза в коде. 1 <= n <= 10^6

UPD: программа из всех ифов задохит только в if(a < 0).....

UPD1: я нашел ошибку. Она была в том, что я обращался к элементам map<ll, ll>, которых в мапе не было. И это, видимо, повлекло утечку памяти или что-то в этом роде

  • Проголосовать: нравится
  • -9
  • Проголосовать: не нравится

»
9 лет назад, # |
  Проголосовать: нравится +8 Проголосовать: не нравится

Вероятно, проблема в строчке ......

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

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

»
9 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Например с тем, что там, где ......, на самом деле есть что-то типа n = 4000000000LL.

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    я сейчас дописал часть кода. тоже вначале подумал об этом

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    if (n  > 1000000)
    {
    	printf("ERROR!!");
    }
    

    дописал, чтобы проверить. в этот иф не заходит

»
9 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Автокомментарий: текст был обновлен пользователем nicky_ua (предыдущая версия, новая версия, сравнить).

»
9 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Автокомментарий: текст был обновлен пользователем nicky_ua (предыдущая версия, новая версия, сравнить).

»
9 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Может ll это на самом деле не long long?

выложи весь код и задачу.

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    я бы выложил, но контест, в котором это задача еще неделю длиться будет(августовский long на codechef'e)

    • »
      »
      »
      9 лет назад, # ^ |
        Проголосовать: нравится +3 Проголосовать: не нравится

      Ну так и спрашивай после контета!

      • »
        »
        »
        »
        9 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        не, ну, просто, ошибка чисто техническая, не по алгоритму/идеи и тд

        • »
          »
          »
          »
          »
          9 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          перенеси свой иф в самое начало. Сразу после считывания.

          Так ты определишь где именно проблема.

»
9 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

ll b = 10000000000000 * n ;

1013·106 = 1019 — переполнение signed типа, то есть undefined behavior

  • »
    »
    9 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    во-первых, лонг лонг до 2^64=1.8×10^19, а во вторых, в иф с b не входит программа, а входит только в иф с a

    • »
      »
      »
      9 лет назад, # ^ |
        Проголосовать: нравится +15 Проголосовать: не нравится

      Вы неправы. long long — тип знаковый, и обычно (в частности, на Codeforces) размером в 64 бита, то есть имеет диапазон значений [ - 263, 263 - 1] ≈ [ - 9·1018, 9·1018]. У вас в программе переполнение знакового типа, что является undefined behavior (как и выход за границы массива, например).

      А один-единственный undefined behavior в программе на C++ делает неопределённым поведение всей программы, в том числе и кусков, не связанных с проблемным местом; они тоже могут начать вести себя неправильно. Как говорил один мой знакомый: "при undefined behavior может произойти всё что угодно, вплоть до звонка вашей бабушке".

      • »
        »
        »
        »
        9 лет назад, # ^ |
          Проголосовать: нравится -8 Проголосовать: не нравится

        Да, действительно. Но программа вылетала и на ограничениях N<=10000. Но я нашел ошибку. Она была в том, что я обращался к элементам map<ll, ll>, которых в мапе не было. И это, видимо, повлекло утечку памяти или что-то в этом роде

        • »
          »
          »
          »
          »
          9 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Утечку памяти — очень вряд ли. Зависит от того, как обращались. Например, если так: m.find(10)->second = 20, то тут тоже неопределённое поведение: если m.find(10) возвращает m.end() (то есть несуществующий элемент), то в него ничего писать нельзя.

          А вот если так: m[10] = 20, то никаких формальных проблем не возникает — оператор [] у map всегда создаёт элемент, если тот не существует. Значение инициализируется по умолчанию (в случае long long'ов — нулём). Если у вас именно этот случай, то, скорее всего, просто ошибка при обработке этих случаев.