Jump to content

    

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

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

Share this post


Link to post
Share on other sites
2 минуты назад, ViKo сказал:

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

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

Share this post


Link to post
Share on other sites
1 минуту назад, MegaVolt сказал:

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

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

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

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

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

z = x * y

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

Share this post


Link to post
Share on other sites
16 минут назад, ViKo сказал:

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

а так ?

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

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

Share this post


Link to post
Share on other sites
2 минуты назад, megajohn сказал:

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

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

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

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

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

Share this post


Link to post
Share on other sites
2 минуты назад, ViKo сказал:

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

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

Share this post


Link to post
Share on other sites
16 минут назад, megajohn сказал:

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

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

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

Share this post


Link to post
Share on other sites
Цитата

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

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

Share this post


Link to post
Share on other sites
7 минут назад, Edit2007 сказал:

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

Да, без.

 

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

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

Не?

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

Share this post


Link to post
Share on other sites
53 минуты назад, ViKo сказал:

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites
13 минут назад, ViKo сказал:

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

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

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

Share this post


Link to post
Share on other sites
6 минут назад, megajohn сказал:

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

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now