Перейти к содержанию
    

Как определить, что произведение двух чисел не переполнит uint64_t?

Хочу в static_assert проверять оговоренное в заголовке условие. Как-то логарифмы сложить? Но не вижу, что получится точно.
К примеру, 7 * 4 = 28, а 7 * 7 = 49. Результат оккупирует разное количество битов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, ViKo сказал:

Хочу в static_assert проверять оговоренное в заголовке условие. Как-то логарифмы сложить? Но не вижу, что получится точно.
К примеру, 7 * 4 = 28, а 7 * 7 = 49. Результат оккупирует разное количество битов.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, MegaVolt сказал:

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

Не следует. Можно 0x1FFF'FFFF'FFFF'FFFF умножить на 2.

1 минуту назад, Forger сказал:

Да вроде как достаточно, чтобы множители были соотв. не больше половины байтов от результата:

static_assert((sizeof(x) + sizeof(y)) <= sizeof(z)))

z = x * y

Не достаточно. Мне с точностью до бита нужно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 минут назад, ViKo сказал:

Не достаточно. Мне с точностью до бита нужно.

а так ?

static_assert(((x) * (y)) > (x))); // и тоже самое для "y"

суть в том, что если было переполнение то произведение будет меньше одного из чисел

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, megajohn сказал:

static_assert(((x) (y)) <= (z)));

А что здесь написано, поясните, пожалуйста. :boredom:

4 минуты назад, megajohn сказал:

static_assert(((x) * (y)) > (x)+(y)));

x * y уже может переполнить uint64_t, никак не сигнализируя. С чем и столкнулся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, ViKo сказал:

А что здесь написано, поясните, пожалуйста. :boredom:

почему-то знаки пропадали после публикации. Выше поправил

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 минут назад, megajohn сказал:

суть в том, что если было переполнение то произведение будет меньше одного из чисел

О, это интересно!

static_assert((x * y) >= x && (x * y) >= y));

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Цитата

static_assert((x * y) >= x && (x * y) >= y));

только при условии что оба числа беззнаковые или одного знака ( -3 * 5 = -15;  -15<-3 <5)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, Edit2007 сказал:

только при условии что оба числа беззнаковые

Да, без.

 

9 минут назад, Arlleex сказал:

static_assert((long double)x*y > ULLONG_MAX, "Overflow!");

Не?

Видимо, да. Только сами x, y в double перевести. А, как раз x и переводится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

53 минуты назад, ViKo сказал:

Не следует. Можно 0x1FFF'FFFF'FFFF'FFFF умножить на 2.

Не достаточно. Мне с точностью до бита нужно.

Ну если всё так серьёзно то для того чтобы проверbть что x*y<z нужно z разделить на x и проверить что результат больше y. Т.е. условие  y<z/x

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Умножаю  1000'000'000'000 на 16'000'000 - ассерт Arllexx срабатывает.
Умножаю 10000'000'000'000 на 16'000'000 - уже нет. 

Метод, предложенный MegaVolt - работает!

static_assert((UINT64_MAX / y) > x, "Over!");

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 минут назад, ViKo сказал:

Метод, предложенный MegaVolt - работает!

static_assert((UINT64_MAX / y) > x, "Over!");

только не забыть проверить на ноль

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 минут назад, megajohn сказал:

только не забыть проверить на ноль

Да. Но если не усложнять то для положительных чисел можно просто к y добавить некоторую дельту.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...