Страница 1 из 1

Глюк Proteus?

Добавлено: Вс июл 24, 2016 18:49:12
Ярослав555
Доброго времени суток уважаемые Коты. Обращаюсь к знатокам МК и Proteus.
Имеем вот такой расчет:
a=400000000
b=(a*4294967296)/1250000000=1374389534.72
Это мне посчитал маткад. Проверил на калькуляторе - сходится.

Теперь вот такой код в IAR для AtMega:

long unsigned int a=0;
long unsigned int b=0;
a=400000000;
b=(long int)(((long float)(a*4294967296))/1250000000);

запускаем Proteus 8.0 и смотрим переменную:

1374389504

Куда делась дробная часть понятно, как позже сделать нормальное округление тоже в курсе. Но куда делась тройка? Почему там 0? Это глюк протеуса?
Если бы я накосячил в коде, то результат бы отличался радикально, а не на один знак в середине числа.

Re: Глюк Proteus?

Добавлено: Вс июл 24, 2016 19:04:31
Ярослав555
Проверил на другом числе - концовка существенно отличается. Похоже что первый случай совпадение. Подскажите как правильно посчитать такие числа на AVRке.

Re: Глюк Proteus?

Добавлено: Вс июл 24, 2016 19:13:46
ARV
изучайте неявное приведение типов операндов в Си.
Ярослав555 писал(а):b=(long int)(((long float)(a*4294967296))/1250000000);
произведение a*4294967296 у вас будет иметь тип long, а потом будет преобразовано в long float (а такое вообще есть?) соответственно, если вы умножаете два long числа и получаете в итоге long-результат, вы сильно теряете в точности. чтобы не потерять в точности надо чтобы хотя бы одно число было long long

Код: Выделить всё

b=(a*4294967296ULL)/1250000000ULL;

Re: Глюк Proteus?

Добавлено: Вс июл 24, 2016 21:10:39
Ярослав555
ок. ошибку кажись понял, заработало, спасибо. но как быть с округлением? без float я теряю дробную часть сразу, floor уже не применить.

Re: Глюк Proteus?

Добавлено: Вс июл 24, 2016 21:15:04
ARV
Ярослав555 писал(а): как быть
я не знаю... если дам совет "думать" - поможет?
не знаю, что именно вы там вычисляете, но сначала умножать на 400000000, а потом делить на 1250000000 - это вызывает вопросы... почему не умножать на 40 и делить на 125?

Re: Глюк Proteus?

Добавлено: Вс июл 24, 2016 21:50:36
Ярослав555
400000000 - это переменная, задается юзером.
1250000000 - это тактовая частота.
4294967296 - это 2^32, константа, емкость счетчика.

AD9850 запускаю. пробовал сразу делить переменную на 0.873114913702. но тоже неочень :)))

Re: Глюк Proteus?

Добавлено: Вс июл 24, 2016 23:57:40
Ярослав555
b=(a*4294967296ULL)/1250000000ULL;
if((((a*4294967296ULL)/125000000ULL)%10)>5){
b++;
}

как-то так, вроде работает, округляет. :)

Re: Глюк Proteus?

Добавлено: Пн июл 25, 2016 00:11:21
Аlex
Ярослав555 писал(а):400000000 - это переменная, задается юзером
Интересно... Не кнопками "+" и "-" случайно ? :)))
В любом случае, почему бы юзеру не задавать более меньшее число ? Арифметика попроще будет.

Re: Глюк Proteus?

Добавлено: Пн июл 25, 2016 00:19:39
Ярослав555
неее :))) кнопками выбираю разряд, валкодером из шаговика устанавливаю число - от десятых герца до десятков мегагерц. Генератору пару лет, все работало, но захотелось пересобрать, косяки убрать, фильтрацию улучшить.

Re: Глюк Proteus?

Добавлено: Пн июл 25, 2016 00:29:52
Аlex
Понятно :)

Тут :
Ярослав555 писал(а):b=(a*4294967296ULL)/1250000000ULL;
if((((a*4294967296ULL)/125000000ULL)%10)>5){
b++;
}
, в условии, можно было бы "b" применить. Для чего повторно высчитывать такие громозкие выражения ? :dont_know:

Re: Глюк Proteus?

Добавлено: Пн июл 25, 2016 05:26:29
ibiza11
Alex, невнимательность тебя погубит)
там не b, a 10b.

Re: Глюк Proteus?

Добавлено: Пн июл 25, 2016 08:40:20
ARV
упс... :roll:

Re: Глюк Proteus?

Добавлено: Пн июл 25, 2016 09:10:43
Ярослав555
Alex посчитайте нолики до if и в самом if. тонкость в том что сначала делю условно на 125000, и получаю допустим 456,78. результат целочисленный, 0,78 отбросили и оно пропало бы. Но в if я делю на 12500, тогда получаю 4567,8. Это МК мне выдает 4567, остаток от деления на 10 будет 7, сравниваем, если больше 5, то инкремент. вот и все :)))

Re: Глюк Proteus?

Добавлено: Пн июл 25, 2016 09:13:30
Ярослав555
а если сразу делить с запасом, то результат не помещается в UL, а если я создаю переменные UUL то МК в протеусе с ума сходит. Я вчера уже и JTAG откопал, и МК нашел, в конце концов осталось только понять что мне там IAR ругается (где-то не настроено). но потом оно в протеусе заработало, и ладно уж :)

Re: Глюк Proteus?

Добавлено: Пн июл 25, 2016 09:33:46
ARV
для округления перед делением на 10 надо всего-навсего прибавить 5, и никаких лишних if не надо.

Re: Глюк Proteus?

Добавлено: Пн июл 25, 2016 09:53:24
Аlex
ibiza11 писал(а):Alex, невнимательность тебя погубит)
там не b, a 10b.
Да, лохонулся, ссори... :oops:

Тогда так :

Код: Выделить всё

b=(a*4294967296ULL)/125000000ULL;
b+=5;
b/=10;
Собственно, тоже самое и предложил ARV.