Pull to refresh

Comments 23

Есть у меня эта книга, только не всю прочитал. Там есть конкретно такой пример? Я не претендую на право первооткрывателя, но приведенный код придуман самостоятельно, хотя он и не сложный, а предварительное гугление результатов не дало
Олег, вы неправильно меня поняли. Я коммент написал не чтобы уличить Вас в переизобретении велосипеда, а к тому, что есть ещё и другие интересные приёмы, про которые полезно почитать, и которые могут часто пригодиться.
результат умножения имеет ту же разрядность, что и множители.

Да ну? Какого типа тогда будет результат умножения unsigned char на unsigned char?
Все арифметические типы Уже int перед арифметикой приводятся к типу int. Т.е. unsigned char * unsigned char = int.
Согласен. Нужно было написать что-то вроде:
«результат умножения целых типа не короче int имеет ту же разрядность, что и множители»
Еще точнее: «C++ не умеет умножать целые короче int, а для целых не короче int разрядность результата совпадает с разрядностью умножения». Для long тоже можно изобрести что-то вроде:
long a, b;
//...
long long c = a*static_cast<long long>(b);

Но это уже выходит за рамки условий поста. Там задача — остаться в рамках исходной разрядности.
> В C/C++, в отличие от большинства ассемблеров,
> результат умножения имеет ту же разрядность, что и множители.

unsigned short a = 60000;
unsigned short b = 60000;
unsigned int i = a*b;

А так?
UFO just landed and posted this here
4.5 Integral promotions — это часть «usual arithmetic conversions».
Вы правы, смотрите мой ответ на предыдущий комментарий
Модельный пример несколько высосан из пальца, ибо гораздо лучшим решением будет использование функции QueryPerformanceCounter.
UFO just landed and posted this here
LARGE_INTEGER c;
QueryPerformanceCounter(&c);
return c.QuadPart;

а в чем должна была быть проблема? этот фрагмент, конечно, забывает про секунды, но если тип результата позволит их вернуть, то можно просто прибавить их, умножив на 1000000000. разница в том, что здесь нет деления и оно не нужно вообще.
нет, все же наврал. делить нужно на соответствующее значение QueryPerformanceFrequency. отличие разве что в том, что делитель здесь небольшой.
… особенно, где-нить на embedded системе вообще без ОС :)
Нет, моедльный пример — в реально работающем проекте. Вот только операционка там — ядро линукс, а все драйвера — свои. Из сторонних библиотек только libc
Не проще ли один раз посчитать TICKS_PER_NSEC?
И чему оно будет равно? Обратите внимание, что в соответствии с условием вещественные типы использовать нельзя
unsigned long long getNsec(unsigned long long ticks) {
    static const unsigned long long _GCD_TPS_NSPS = gcd(NSEC_PER_SECOND, TICKS_PER_SECOND);
    return ticks * (NSEC_PER_SECOND / _GCD_TPS_NSPS) / (TICKS_PER_SECOND / _GCD_TPS_NSPS);
};


Я для упрощения округлил до 1999000000ULL, полагая, что значение роли не играет. Считайте gcd = 1, такое будет, например, для TICKS_PER_SECOND = 1999000001ULL;
Сделал соответствующее исправление в тексте, чтобы не возникало дальнейших вопросов с GCD. Стоит также заметить, что в исходной задаче константы были взаимно просты, и лишь при подготовке начального варианта поста я произвел округление, которое по моему недогляду привело к еще одному решению через GCD.
Все корректно. Кое где можно было бы привести умножение вместо второй операции '%' — может съэкономить пару тактов, если часто вызываема будет, поскольку операция деления и взятия остатка не сможет быть даже гипотетически объединена в одну операцию конвеером процессора (существуют в разрыв им другие операции). Нахождение общего делителя интересный момент, но гораздо хуже, если коэффициенты будут иметь единицу в качестве онного.
Sign up to leave a comment.

Articles