Zaokrouhlení na desitky – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Zaokrouhlení na desitky – C / C++ – Fórum – Programujte.comZaokrouhlení na desitky – C / C++ – Fórum – Programujte.com

 

Boblig0
Newbie
11. 4. 2013   #1
-
0
-

   Ahoj, potřebuju čtyřciferné celé číslo zaokrouhlit na tříciferné (ve skutečnosti tisíciny na setiny), vymyslel jsem tento algoritnus, avšak po sobě jdoucí čísla 3422, 3426 dávají najevo, že je něco špatně, logicky bych očekával 3422, 3431. Věděl by někdo co s tím? Díky       

          U=((long)adc*5000/1024);                          // adc=<0;1023>
              if ( (((u%1000)%100)%10) >= 5)  {u+5;}  // otestuj jednotky zda jsou >= 5, případně přičti 5 k U
                 else {U+0;}                                       // v případě < 5 nech původní U

         tisice=U/1000;   //
          // desetina carka
         stovky=(U%1000)/100; //
         desitky=((U%1000)%100)/10; //
            //  jednotky=((U%1000)%100)%10; // potlačeny !

Nahlásit jako SPAM
IP: 89.102.186.–
crazy
~ Moderátor
+10
Grafoman
11. 4. 2013   #2
-
0
-

#1 Boblig
nechápu to, ale pokud chceš aby se ti číslo, které má v jednotkách číslici >= 5 tak aby se zaokouhlilo na desítky nahoru, tak stačí toto:

if( cislo % 10 >= 5 )
{
	cislo += 5;
	cislo /= 10;
	cislo *= 10;
}
Nahlásit jako SPAM
IP: 147.32.31.–
All you need is vision and time.
Flowy0
Věrný člen
11. 4. 2013   #3
-
0
-

a este trochu prirodzenejsie

if (cislo%10>=5) { cislo += 10 - (cislo%10); }
else { cislo -= cislo%10; }

btw tisiciny a setiny su za desatinnou ciarkou ... pred nou sa to pocita ako tisicky a stovky

Nahlásit jako SPAM
IP: 178.41.163.–
https://github.com/Flowy
crazy
~ Moderátor
+10
Grafoman
11. 4. 2013   #4
-
0
-

#3 Flowy
pochopil jsem to tak ze chce zaokrouhlovat pouze nahoru pokud to bude mit jednotky vetsi nez 5, jinak to ma zustat stejne

Nahlásit jako SPAM
IP: 147.32.31.–
All you need is vision and time.
Flowy0
Věrný člen
11. 4. 2013   #5
-
0
-

to else som tam pridal keby nahodou chcel normalne zaokruhlovat ... kazdopadne pricitat to cislo je myslim prirodzenejsie a jednoduchsie sa to upravuje

Nahlásit jako SPAM
IP: 178.41.163.–
https://github.com/Flowy
KIIV
~ Moderátor
+43
God of flame
11. 4. 2013   #6
-
0
-

#3 Flowy
jelikoz dela s ADC a je to pravdepodobne na jednocipu typu atmega, + ma tam vypocet  5000 (jako 5V) a nasobeni 1024... tak to ve skutecnosti setiny a tisiciny opravdu budou :)

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Boblig0
Newbie
11. 4. 2013   #7
-
0
-

#4 crazy
Nikoliv, má to zaokrouhlovat nahoru i dolu, schválně to rozepíšu ať je to názornější jak jsem to myslel, pro příklad dám hodnoty od 3420-3429, z toho to snad bude pochopitelnější

3420 - jednotky nejsou >=5, nech bejt >>> 3420 >>> 3,42
...

3424 - jednotky nejsou >=5, nech bejt >>> 3424 >>> 3,42
3425 - jednotky jsou >=5, přičti 5 >>> 3430 >>> 3,43
...

3429 - jednotky jsou >=5, přičti 5 >>> 3434 >>> 3,43
3430 - jednotky nejsou >=5, nech bejt >>> 3430 >>> 3,43

a přeformátuju to tak, že přes modulo to rozsekám na cifry a vypíšu to znak po znaku s tím, že mezi stovky a tísíce vložim čárku viz první příspěvek dole. 

Nahlásit jako SPAM
IP: 89.102.186.–
KIIV
~ Moderátor
+43
God of flame
11. 4. 2013   #8
-
-1
-
Mimo téma

no to se fakt dela tak ze prictes tu petku... a pri vypisovani pak jen zpracuj tri cislovky .. posledni klidne vynech

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
KIIV
~ Moderátor
+43
God of flame
11. 4. 2013   #9
-
+1
-
Zajímavé

tak co teda resis, kdyz to mas a vsechno vis?

Abych jeste dokoncil predchozi myslenku:

3420+5 = 3425 alias 342
3421+5 = 3426 alias 342
3422+5 = 3427 alias 342
3423+5 = 3428 alias 342
3424+5 = 3429 alias 342
3425+5 = 3430 alias 343
3426+5 = 3431 alias 343
3427+5 = 3432 alias 343
3428+5 = 3433 alias 343
3429+5 = 3434 alias 343

WOW, neuveritelne, neni potreba zadnej if

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Boblig0
Newbie
12. 4. 2013   #10
-
0
-

#9 KIIV
Máte pravdu, tu pětku mohu přičíst ke všemu a na výsledek to nemá vliv, takže ten if netřeba, to me nenapadlo, zřejmně sem to měl v hlavě z nějakého jiného případu. Nicméně ten zápis v prvním příspěvku je stejně záhadně nefunkční.

Nahlásit jako SPAM
IP: 89.102.186.–
Boblig0
Newbie
12. 4. 2013   #11
-
0
-

Ale teď sem narazil na zajímavý problém související v tím výše, udělal jsem si výpis několika hodnot pomocí seriové linky a zjistil sem, že výsledky se kupodivu neshodují, výpis viz odkaz http://www.imgway.cz/di-J66W.jpg

První sloupec je čas, druhý sloupec jsou původní hodnoty s tisícinama, ve třetím jsem pouze přičetl 5 což odpovídá a ve čtvrtém jsem pouze nevypsal tisíciny toho třetího, avšak hodnoty se místy záhadně odchylují, přitom rozdíl mezi třetím a čtvrtým slupcem je pouze v tom, že jsem zakomentoval výpis tisícin  -  // uart_putc('0'+tisiciny); 

Nahlásit jako SPAM
IP: 89.102.186.–
KIIV
~ Moderátor
+43
God of flame
12. 4. 2013   #12
-
0
-

#11 Boblig
dej sem asi aktualni kod... aby se to takhle menilo pod rukama je prinejmensim podezdele...

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Boblig0
Newbie
12. 4. 2013   #13
-
0
-

Uvedu jen tu část přerušení, kde dochází k výpočtu a výpisu abych to tu netapetoval, celý kód kdyžtak později.


signed short int u, jednotky, desetiny, setiny, tisiciny;
unsigned long int counter=0;  // 0 - 99999
volatile unsigned short int adc;

ISR(TIMER1_OVF_vect)
{
counter++;
uart_putc('0'+counter/100);
uart_putc('0'+counter%100/10);
uart_putc('0'+counter%10);
uart_putc(';');  // format csv

 u = ((long)adc*4096/1024)+5; 

 if (u>=0) {jednotky=u/1000;}
      else {jednotky=(u*(-1))/1000;}

if (u>=0) {desetiny=(u%1000)/100;}
   else {desetiny=((u*(-1))%1000)/100;}  

if (u>=0) {setiny=((u%1000)%100)/10;}
   else {setiny=(((u*(-1))%1000)%100)/10;}
   
  if (u>=0) {tisiciny=((u%1000)%100)%10;}
       else {tisiciny=(((u*(-1))%1000)%100)%10;}
                
if (u>=0) {uart_putc('+');}
   else {uart_putc('-');}
   
      uart_putc('0'+jednotky);
      uart_putc(',');
      uart_putc('0'+desetiny);
      uart_putc('0'+setiny);
       // uart_putc('0'+tisiciny);
    
      uart_putc(';'); // format csv
      uart_putc(';'); // format csv
      uart_putc(13); //carriage return

Nahlásit jako SPAM
IP: 89.102.186.–
12. 4. 2013   #14
-
0
-

s jakou četností se ISR volá? Neobsluhuje procesor i další ISR? S jakou rezervou obsluhu ISR stíhá?

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Boblig0
Newbie
12. 4. 2013   #15
-
0
-

CPU obluhuje pouze tento ISR, je nastaven po 0,1 sekundách a UART běží na 57600 Baud, s jakou rezervou ISR stíhá to bohužel nevím kde zjistit.

Nahlásit jako SPAM
IP: 89.102.186.–
KIIV
~ Moderátor
+43
God of flame
12. 4. 2013   #16
-
0
-

kazdopadne s tolika delenima, zbytkama po deleni to bude brutalne pomaly... to samy cekani na poslani dalsiho znaku a tak...    kdyby aspon kompilator mel nejakou inteligenci a dokazal si rict ze   ((u%1000)%100)%10  je jen   u%10  

a kdyz uz to delas do promennych tak se to dalo udelat opacne:

tisiciny = u%10;

u /= 10;

setiny = u%10;

u /= 10;

....

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Boblig0
Newbie
12. 4. 2013   #17
-
0
-

Díky, to dělení odzadu mě nenapadlo. Zkusil sem to opravit, ale když dám vypsat jen tři čísla, tak se výsledky pořád záhadně mění. Vypadá to, že se při výpisu bez tisícin někde integruje nějaká chyba...

Nahlásit jako SPAM
IP: 89.102.186.–
KIIV
~ Moderátor
+43
God of flame
12. 4. 2013   #18
-
0
-

kde tam vlastne beres ty zaporny cisla? Adc mas jako diferencialni?

si to du asi naprogramovat at vim co se deje :D

Nahlásit jako SPAM
IP: 94.113.92.–
Program vždy dělá to co naprogramujete, ne to co chcete...
KIIV
~ Moderátor
+43
God of flame
12. 4. 2013   #19
-
0
-

pocita mi to dobre.. tam budes mit asi nejaky jiny problem...

Nahlásit jako SPAM
IP: 94.113.92.–
Program vždy dělá to co naprogramujete, ne to co chcete...
KIIV
~ Moderátor
+43
God of flame
12. 4. 2013   #20
-
0
-

 Pro predstavu:

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>

volatile uint8_t  state=0;
volatile uint16_t adc_val;

uint8_t str[5] = {0,0,0,0,0};
 int8_t stri   = 0; 

ISR(TIMER1_COMPA_vect) {
  PINC = _BV(PC7); // toggle PC7
  ADCSRA |= _BV(ADSC);
}

ISR(ADC_vect) {
  if (state==0) {
    adc_val=ADC;
    state=1;
  }
}

void usart0_put(uint8_t c);

int main( void ) {
  DDRD = _BV(PD1); // TXD0 as output
  DDRC = _BV(PC7); // PC7 as output...

  // usart0:
  UBRR0 = 34;  // 16MHz, 57600bauds, ...
  UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); // async, no parity, 1 stop, 8 bit
  UCSR0A = _BV(U2X0); // double speed (better error with prescaler on 34)
  UCSR0B = _BV(TXEN0)  |  _BV(RXEN0); // enable transmitter

  // T1 
  TCCR1A = 0; 
  TCCR1B = _BV(WGM12) | _BV(CS12) | _BV(CS10) ;  //WGM1* = 4; prescaler :1024
  //OCR1A  = 15625 -1; // 1000ms
  OCR1A  = 3125 -1; // 200ms
  TIMSK1 = _BV(OCIE0A); // compare match interrupt

  // ADC:
  ADMUX  = _BV(REFS1) | _BV(REFS0) ; // input ADC0, Ref 2.56V
  ADCSRA = _BV(ADEN) | /*_BV(ADATE) |*/ _BV(ADIE) | 7; // division 7 -> :128
  //ADCSRB = 5; // ADTS=5  -> timer 2 compare B match
  DIDR0 = 0xFF; // disable all PORTA digital functions


  sei(); // interrupt's enable
  while (1) {
    if (state==1) {
      uint16_t u = adc_val;
      u *= 49;
      for (stri=0; stri<5; ++stri){
        str[stri] = u%10;
        u /= 10;
      }
      for (stri=4; stri>=1; --stri) {
        usart0_put('0'+str[stri]);
      }
      usart0_put(';');
      state=2;
    } else if (state==2) {
      uint16_t u = adc_val;
      u *= 49;
      u += 50;
      for (stri=0; stri<5; ++stri){
        str[stri] = u%10;
        u /= 10;
      }
      for (stri=4; stri>=1; --stri) {
        usart0_put('0'+str[stri]);
      }
      usart0_put('\r');
      usart0_put('\n');
      state=0;
    }
  }
}

void usart0_put(uint8_t c) {
  if (!(UCSR0B & _BV(TXEN0))) return; // skip if TX0 not enabled 
  while (!(UCSR0A & _BV(UDRE0))) {;}
  UDR0 = c;
}
Nahlásit jako SPAM
IP: 94.113.92.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Boblig0
Newbie
12. 4. 2013   #21
-
0
-

Ano, před vstupem ADC mám sumátor, kde přičítám polovinu reference a následně jí v programu odečítám, takže mohu přivádět i záporné signály. Možná bude problém v tom, že to nezkouším v reálu, ale pouze simulačně v PSpicu, takže možná by mohl být zádrhel zde. Reálně bych pak chtěl krystal 14,745 MHz, USART na 115200 Baudů a data posílat rychlostí 600-800 vzorků za vteřinu přes FT232RL na terminál. Ale abych se vrátil k tématu, kdyby byl nějaký problém s těmi desetinými místy, tak to prostě nechám nezaokrouhlené i když je otázka jak to vlastně potom zjistím.

pro ukázku celý program

Nahlásit jako SPAM
IP: 89.102.186.–
KIIV
~ Moderátor
+43
God of flame
12. 4. 2013   #22
-
0
-

no kazdopadne se v tom tvym programu da trosku zjednodusovat... zapnout treba CTC mod timeru.. nebudes pak muset nastavovat pokazdy nejakou hodnotu, od ktere pocitat nahoru...

veci jako  4096/1024 se daji rovnou vykratit (nebo doufat ze to udela aspon kompilator)

nedavat do ISR nic co trva dlouho... nechavat tak kratke, jak jen to jde

a tak dale

Nahlásit jako SPAM
IP: 94.113.92.–
Program vždy dělá to co naprogramujete, ne to co chcete...
13. 4. 2013   #23
-
0
-

800 Sps. To bych na úrovni jednočipu nic nepočítal a už vůbec ne float point. zformátovat výstup ADC v hexadecimálním tvaru a po "balíčcích" odeslat přes USB.

hu

Nahlásit jako SPAM
IP: 188.95.60.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 99 hostů

Podobná vlákna

Zaokrouhlení — založil Standa

Zaokrouhlení double — založil Redby

Zaokrouhlení čísel — založil pauli975

Zaokrouhlení double — založil vollf82

Zaokrouhlení na stovky — založil FeXxy

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý