Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

Закръгляване
http://mcu-bg.com/mcu_site/viewtopic.php?f=14&t=15331
Страница 1 от 2

Автор:  Н'бабане Гт'муан'га [ Сря Юни 21, 2017 10:51 am ]
Заглавие:  Закръгляване

... до най-близка граница.
Примерно при граница 0.5 всички резултати от закръгляването завършват или на .0, или на .5, при граница 0.25 всички резултати са или .0 или .25 или .5 или .75, и т.н...
Някакви идеи как стане?

ПС.... погрешка пуснах темата в грешен раздел. Рек или някой друг админ ако може да я премести в "Програмиране..."

Автор:  palavrov [ Сря Юни 21, 2017 11:04 am ]
Заглавие:  Re: Закръгляване

Класическия алгоритъм е с изваждане на остатъка от делене като предварително е добавен половин делител за да закръгли към по близкия резултат. Т.е.

int round(v, r) { return v - (v+r/2) % r; }

Автор:  Gogo [ Сря Юни 21, 2017 2:50 pm ]
Заглавие:  Re: Закръгляване

Ако работиш компилатор на микрочеп, не търси round() функция - няма...

Автор:  TheWizard [ Сря Юни 21, 2017 3:47 pm ]
Заглавие:  Re: Закръгляване

Gogo написа:
Ако работиш компилатор на микрочеп, не търси round() функция - няма...


double ceil(double);
double floor(double);

http://www.cplusplus.com/reference/cmath/floor/
http://www.cplusplus.com/reference/cmath/ceil/

ма не са на 0.5

Автор:  Н'бабане Гт'муан'га [ Сря Юни 21, 2017 3:54 pm ]
Заглавие:  Re: Закръгляване

Абе забравих да спомена. Сигурно е забавно, но това ми трябва на бъзик (разбирай "бейсик" :))

Автор:  bobihot [ Сря Юни 21, 2017 5:39 pm ]
Заглавие:  Re: Закръгляване

Ako са такива кратни- умножаваш по 2|4 закръгляш и делиш на толкова.

Автор:  Reader [ Чет Юни 22, 2017 8:30 am ]
Заглавие:  Re: Закръгляване

palavrov написа:
Класическия алгоритъм е с изваждане на остатъка от делене като предварително е добавен половин делител за да закръгли към по близкия резултат. Т.е.
int round(v, r) { return v - (v+r/2) % r; }

Не съм убеден, че това работи. По-практичен е следният алгоритъм:
Код:
int(v/r+0.5).r

Автор:  palavrov [ Чет Юни 22, 2017 8:51 am ]
Заглавие:  Re: Закръгляване

Reader написа:
palavrov написа:
Класическия алгоритъм е с изваждане на остатъка от делене като предварително е добавен половин делител за да закръгли към по близкия резултат. Т.е.
int round(v, r) { return v - (v+r/2) % r; }

Не съм убеден, че това работи. По-практичен е следният алгоритъм:
Код:
int(v/r+0.5).r

Колега, хайде да го разнищим това което си написал:
(v/r + 0.5)*r = (v/r +1/2)*r = (r*v/r + r/2) = v+r/2 - до тук същото само, че с различна формула :)
int(v+r/2) има същият ефект като v-(v+1/2)%1 само, че в случая приравняваш r=1 и то не за цялата формула която съм написал т.е. така като си го написал няма да работи вярно за 0.25 примерно. В моя пример единственото грешно нещо е, че използвам % вместо fmod() - но все пак предполагам, че четящите тук са достатъчно компетенти по отношение на C/C++ оператори и RTL за се сетят и сами как да го модифицират за double. Ако числата на които трябва да се закръгля са винаги във формата 1/n тогава може да се избяга от сметки с плаваща запетая като се умножава и дели на n - едва ли обаче се налага да се оптимизира чак дотолкова, че да се цепи инструкцията и/или такт-а.

Автор:  Н'бабане Гт'муан'га [ Чет Юни 22, 2017 11:40 am ]
Заглавие:  Re: Закръгляване

е, в крайна сметка с идеи оттук стигнах до приемливо решение. Ето как изглежда на бейсика: float v=int(v/r)/(1/r)

Автор:  Reader [ Чет Юни 22, 2017 12:29 pm ]
Заглавие:  Re: Закръгляване

palavrov написа:
Колега, хайде да го разнищим това което си написал:

Хайде да не спорим, а просто да заместим например v=0.8 и r=0.5 в твоята формула. Получаваме:
0.8 - (0.8 + 0.25) % 0.5 = 0.8 - (1.05 % 0.5) = 0.8 - 0.05 = 0.795
т.е. нищо близко до правилния отговор.
А грешката в преобразуванията, които правиш, е че приравняваш x.int(y) на int(x.y), което не е коректно.

И изобщо – темата е приключена; отворилият я е стигнал до приемливо за него решение.

Автор:  Reader [ Чет Юни 22, 2017 12:38 pm ]
Заглавие:  Re: Закръгляване

Н'бабане Гт'муан'га написа:
е, в крайна сметка с идеи оттук стигнах до приемливо решение. Ето как изглежда на бейсика: float v=int(v/r)/(1/r)

Липсва ти добавянето на половинката в int-а; в момента формулата ти реализира floor(), а не round(). И ако r е float, защо да не е v = r*int(v/r + 0.5)

Автор:  Н'бабане Гт'муан'га [ Чет Юни 22, 2017 1:43 pm ]
Заглавие:  Re: Закръгляване

Reader написа:
Н'бабане Гт'муан'га написа:
е, в крайна сметка с идеи оттук стигнах до приемливо решение. Ето как изглежда на бейсика: float v=int(v/r)/(1/r)

Липсва ти добавянето на половинката в int-а; в момента формулата ти реализира floor(), а не round(). И ако r е float, защо да не е v = r*int(v/r + 0.5)


Във версията която ползвам INT() закръглява а не реже целочислено

Автор:  Reader [ Чет Юни 22, 2017 1:49 pm ]
Заглавие:  Re: Закръгляване

Тогава извинявай – всичко е точно! :)

Автор:  palavrov [ Чет Юни 22, 2017 3:52 pm ]
Заглавие:  Re: Закръгляване

Reader написа:
palavrov написа:
Колега, хайде да го разнищим това което си написал:

Хайде да не спорим, а просто да заместим например v=0.8 и r=0.5 в твоята формула. Получаваме:
0.8 - (0.8 + 0.25) % 0.5 = 0.8 - (1.05 % 0.5) = 0.8 - 0.05 = 0.795
т.е. нищо близко до правилния отговор.
А грешката в преобразуванията, които правиш, е че приравняваш x.int(y) на int(x.y), което не е коректно.

И изобщо – темата е приключена; отворилият я е стигнал до приемливо за него решение.

Мдам - прав си, че имам грешка но не е в това което казваш и е сравнително лесна за оправяне:

(v+r/2)-(v+r/2)%r

А твоята формулата също става, че е и по елегантна, евала:

round(v/r) * r

Автор:  relsys [ Пет Юни 23, 2017 11:10 am ]
Заглавие:  Re: Закръгляване

А как се изчислява ДДС на касова бележка от 1 стотинка?

Страница 1 от 2 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/