Rozdeleni 8bitoveho integeru na dve casti – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Rozdeleni 8bitoveho integeru na dve casti – C / C++ – Fórum – Programujte.comRozdeleni 8bitoveho integeru na dve casti – C / C++ – Fórum – Programujte.com

 

19. 11. 2008   #1
-
0
-

Mam 8bitovy unsigned integer, do ktereho ukladam dve ruzne informace

Leva polovina (v hexa zapisu je to levy znak) - informace typu ano/ne, koduji ano jako F a ne jako 0.
Prava polovina - ciselna informace (vetsinou v rozsahu 0-8, neni to ale striktne dane).

Celkova hodnota pro hodnotu ano/4 tedy vypada v hexa zapisu (decimalni je docela dost irelevantni) jako 0xF4. Ne/8 je pak 0x08.

O co mi jde: od prave poloviny potrebuju co nejrychleji odecitat / pricitat cislo 1 - a to pokud mozno aniz bych musel explicitne zjistovat hodnotu promenne. Problem uz je asi zrejmy: staci k 0x08 parkrat pricist jedna a hned je z toho 0xF0, coz je nezadouci, protoze prava polovina nesmi na levou mit vliv, jedna se o dve oddelene informace. To same se stane, kdyz od F0 (tedy ano/0) odectu jedna.

Dotaz tedy zni: Jak nejrychleji bezpecne zvetsit/zmensit hodnotu prave poloviny o jedna?

Jedna se mi opravdu o rychlost - tato uloha se typicky ma provadet treba 4 000 000 krat za sekundu. To, abych si to osetril podminkami je tedy neprijatelne, to uz bych mel rychlejsi to rozdelit do dvou promennych.

Jesli nekdo prijdete s lepsim zpusobem, jak tyto dve informace ukladat do jedne promenne, tak sem s nim, v kodu se mi to vyskytuje na par mistech a neni problem to zmenit. Upozornuji, ze ale cteni ma jeste podstatne vetsi prioritu nez zapis. Napadlo me treba ukladat ne hodnoty jako x*2 a ano hodnoty jako x*2+1, ale tam by znamenalo pri kazdem cteni delit dvema, coz je zbytecne pomale. Jde mi o jednoduche porovnavaci podminky typu

if(*cache < 0xF0 && *cache != 0x03) ...
...tj. jestli je leva strana ne a prava neni 3, tak proved kod.

Vecna slava a tucet panen v nebi uspesnemu resiteli :smile1:

Nahlásit jako SPAM
IP: 81.30.238.–
Prosím, jestli potřebujete s něčím poradit,zeptejte se na fóru. Jakýkoliv bezdůvodný pokus mě kontaktovat skončí okamžitým přidáním do ignore listu![br][br] Současný počet osob, které to nepochopily: 7
KIIV
~ Moderátor
+43
God of flame
19. 11. 2008   #2
-
0
-

ja sem resil neco podobneho:

int neco ;
unsigned char * cislo = (unsigned char *) &neco;

cislo[0] bude nejnizsich 8b
cislo[1] bude tech dalsich 8b

ale bacha na ruzne architektury... toto facha na pc .. s little endian... (teda snad sem si to nespletl :D)

Nahlásit jako SPAM
IP: 80.250.27.–
Program vždy dělá to co naprogramujete, ne to co chcete...
19. 11. 2008   #3
-
0
-

Jenze tohle uz je char :)

Tady je typedef toho co puzivam:

typedef unsigned char    uint8;


Neda se treba necim vycarovat 4bitovy datovy typ? To by to pak slo udelat analogicky, tj. pricitat pouze k tem druhym 4 bitum.

Ted me napadla dalsi moznost:
Kodovat to ano/ne v prvni polovine jako 1 a 0, ne jako F a 0. To bych pak s tim pri zapisu mohl pracovat jako s signed 8bit integerem (jestli je znamenko definovano 1. bitem jak predpokladam), jenze potom by pricteni ve stavu, kdy by znamenko bylo - bylo vlasne odecte...ach jo, to by znamenalo zase delat podminky :(

PS: K architekture - je mi jedno na cem to pobezi, staci aby to jelo na Woknech a pokud mozno i Linuxu.

Nahlásit jako SPAM
IP: 81.30.238.–
Prosím, jestli potřebujete s něčím poradit,zeptejte se na fóru. Jakýkoliv bezdůvodný pokus mě kontaktovat skončí okamžitým přidáním do ignore listu![br][br] Současný počet osob, které to nepochopily: 7
KIIV
~ Moderátor
+43
God of flame
20. 11. 2008   #4
-
0
-

jo aha sem cetl integer tak sem myslel ze to je 4B promenna (nebo minimalne aspon 16) :D

u jednodussich procesoru bylo neco jako swap nibbles ale tezko rict jestli je to i nejak snadno dostupne v C


kdyztak nejrychlejsi zvetseni prave poloviny o 1 je myslim asi pricist 16

Nahlásit jako SPAM
IP: 80.250.27.–
Program vždy dělá to co naprogramujete, ne to co chcete...
ondra.holub
~ Anonymní uživatel
255 příspěvků
20. 11. 2008   #5
-
0
-

V C např. takto:

#include <stdio.h>

#include <stdint.h>

enum YesNo
{
NO = 0x0,
YES = 0xF
};

struct Xyz
{
unsigned data_:4;
unsigned yes_no_:4;
};

union Int4
{
struct Xyz xyz_;
uint8_t integer_;
};

int main(void)
{
union Int4 i4;
i4.xyz_.yes_no_ = YES;
i4.xyz_.data_ = 5;

printf("0x%x\n", i4.integer_);

for (int i = 0; i < 20; ++i)
{
i4.xyz_.data_++;
printf("0x%x\n", i4.integer_);
}

return 0;
}


Pokud by to dělalo problémy s little a big endian, tak lze pořadí v té struktuře změnit na základě nějakého #ifdefu. Obecně je možné nadělat si nějaké přístupové funkce pro jednodušší přístup.

V C++ bych to řešil podobně, jenom by se to dalo ještě zabalit do nějaké třídy a dodefinovat inline přístupové metody nebo nějaké operátory, např. ++ a -- by měnily jenom tu integerovou část, apod. Podle libosti a potřeby.

Nahlásit jako SPAM
IP: 194.138.12.–
20. 11. 2008   #6
-
0
-

Co presne je tenhle zapis:

unsigned data_:4;


To je ten 4bitovy integer? Da se to pouzit i v kombinaci s typedefem abych k tomu mohl pristupovat rovnou a ne pres strukturu?

A diky, vypada to zajimave, doma si s tim zkusim pohrat.

Nahlásit jako SPAM
IP: 78.102.164.–
Prosím, jestli potřebujete s něčím poradit,zeptejte se na fóru. Jakýkoliv bezdůvodný pokus mě kontaktovat skončí okamžitým přidáním do ignore listu![br][br] Současný počet osob, které to nepochopily: 7
MaS0
Návštěvník
20. 11. 2008   #7
-
0
-

šlo by to takto...

void zvetsit(char& a) {

a++;
a&=0xF;
cout << (int) a;
}

přičítá to čísla až do 15 a po překročení to jede znova......podle mě je lepší to ano/ne uchovávat v prvním bitu (napsat tam a&=0x7F)...

mohl bych se zeptat: "To je ta podmínka náročnější, než jiný operace *, /, +, -, ... ?"

Nahlásit jako SPAM
IP: 195.146.114.–
MaS0
Návštěvník
20. 11. 2008   #8
-
0
-

ještě jsem zapomněl, že před voláním funkce zvetsit se mu získat hodnota ano/ne

char * b=&a;

b&0xF0;
na to je lepší uchovávat ano/ne v prvním bitu (bool * b=&a;)
a poté zase uložit
a|=(*b);

Nahlásit jako SPAM
IP: 195.146.114.–
bukaj_0010
Věrný člen
20. 11. 2008   #9
-
0
-

ondra.holub
Použít bitové pole asi nebude to pravé ořechové, jelikož se jeho velikost, alespoň myslím, zaokrouhluje na počet bitů intu.

Nahlásit jako SPAM
IP: 85.70.13.–
Jak se správně ptát? -> http://www.hash.cz/inferno/otazky.html[br][br] Po programování je člověk hladovej.
Nykodym
~ Anonymní uživatel
6 příspěvků
20. 11. 2008   #10
-
0
-

To CommanderZ : Je to bitové pole. Definuje se podobně jako struktura (jak je vidět :-)), ale ještě se napíše dvojtečka za každou proměnnou a za ni počet bitů které jsou pro danou proměnnou rezervovány. Celkový součet bitů by ideálně měl dát nějaké "kulaté" číslo třeba 8, 16, atd. Pomocí bitového pole je definována např. struktura ftime v <dos.h>. Asi nejvíc se hodí na šetření paměti (programování mikrokontrolérů). Rychlost přístupu je myslím jako u každé jiné struktury (pouze teoretizuji, chce to vyzkoušet). Pro rychlé změny hodnot proměnných jsou asi nejlepší binární operátory, optimalizace na rychlost leccos zvládne, ale není od věci vypsat to všechno ručně.

Nahlásit jako SPAM
IP: 147.229.194.–
20. 11. 2008   #11
-
0
-

Hmm, zda se ze poblem nikdy ani nenastal :( :)

Neocekavane chovani bylo zpusobeno hloupou chybou v kodu, ne spatnym principem. Zda se totiz, ze princip aplikace zabranuje tomu, aby ty hodnoty pretekly/podtekly a jsou drzeny opravdu v rozsahu 0-8.

Trochu me ale zklamal vykon - razantne jsem snizil pocet cteni z promennych za cenu pouze jednoho zapisu navic (a to jen v nekterych situacich) a podle profileru klesl vykon testu, ktery jsem predtim provadel za 21 vterin, na 23.5 vteriny :( Tak nejak doufam ze dneska ma muj pocitac jenom spatnou naladu, protoze mi to prijde fakt dost nemozne.

Ale to nic nemeni na tom, ze se stejne budu snazit vykoumat, jak to pro priste udelat :)

Nahlásit jako SPAM
IP: 81.30.238.–
Prosím, jestli potřebujete s něčím poradit,zeptejte se na fóru. Jakýkoliv bezdůvodný pokus mě kontaktovat skončí okamžitým přidáním do ignore listu![br][br] Současný počet osob, které to nepochopily: 7
tmi0
Věrný člen
21. 11. 2008   #12
-
0
-

myslim ze by bylo lepsi delat to pres dve promenne, pokud nepotrebujes obzvlaste setrit pameti.
uz jenom proto, ze char je nejmensi jednotka jakou jazyk c podle standardu smi primo adresovat, takze adresace poloviny charu te stoji instrukci navic.
pokud by jsi to chtel delat pres bitove operace, pak ikrementace vyssi poloviny je jednoducha, tedy c+=16; (tady to vyjde stejne draho jako obycejna inkrementace), inkrementace nizsi poloviny by byla o neco slozitejsi, napriklad c=(c&240) + (c+1)&(15); coz uz te stoji o dost vic (ale rekl bych ze o moc rychleji to dnesni procesory optimalizovane na praci s 64bitovymi cisly nevymisli) ale je to docela elegantni a kratke. ale psat tam podminku by bylo skutecne hloupe...

Nahlásit jako SPAM
IP: 213.226.230.–
ksp.mff.cuni.cz -- doporučuje 5 z 0 přetečených bufferů!
ondra.holub+1
Stálý člen
22. 11. 2008   #13
-
0
-

To bukaj_001 : Použít bitové pole asi nebude to pravé ořechové, jelikož se jeho velikost, alespoň myslím, zaokrouhluje na počet bitů intu.
Pokud se bude jednat o proměnnou na zásobníku, tak je to jedno. To zaokrouhlení bude stejné. Buď to bude zarovnané na nějaké násobky 4 (nebo 8) bajtů nebo to bude zkomprimované, ale pomalejší. To zarovnání bude stejné jako zarovnání struktury nebo unionu.
Jediný rozdíl je v případě, že to chci mít uloženo v poli souvisle za sebou. Tady ale obvykle není problém mít ukazatel na konkrétní prvek, takže ten ukazatel stačí přetypovat na ten union a je to zase triviální. Přetypování nestojí v runtime nic. ZBytek udělá překladač a věřil bych tomu, že pro danou platformu to udělá hodně dobře.

Nahlásit jako SPAM
IP: 89.203.160.–
22. 11. 2008   #14
-
0
-

ondra.holub napsal:
To bukaj_001 : Použít bitové pole asi nebude to pravé ořechové, jelikož se jeho velikost, alespoň myslím, zaokrouhluje na počet bitů intu.
Pokud se bude jednat o proměnnou na zásobníku, tak je to jedno. To zaokrouhlení bude stejné. Buď to bude zarovnané na nějaké násobky 4 (nebo 8) bajtů nebo to bude zkomprimované, ale pomalejší. To zarovnání bude stejné jako zarovnání struktury nebo unionu.
Jediný rozdíl je v případě, že to chci mít uloženo v poli souvisle za sebou. Tady ale obvykle není problém mít ukazatel na konkrétní prvek, takže ten ukazatel stačí přetypovat na ten union a je to zase triviální. Přetypování nestojí v runtime nic. ZBytek udělá překladač a věřil bych tomu, že pro danou platformu to udělá hodně dobře.



Takze jak tedy ve vysledku vypada v pameti ta bitova struktura, ktery jsi uvedl v prikladu nahore? Je to tohle (A jsou bity datove slozky 1, B jsou bity datove slozky 2, | opticky oddeluji jednotlive prvky v poli):
AAAABBBB|AAAABBBB|AAAABBBB...

nebo
AAAAAAAABBBBBBBB|AAAAAAAABBBBBBBB|AAA...

nebo nejak jinak? To by vysletlovalo ty chyby, ktere mi to vyhazovalo pri pokusu pristoupit k prvkum v druhe polovine pole...(ktere bylo puvodne definovane jako pole 8bit integeru).

Nahlásit jako SPAM
IP: 81.30.238.–
Prosím, jestli potřebujete s něčím poradit,zeptejte se na fóru. Jakýkoliv bezdůvodný pokus mě kontaktovat skončí okamžitým přidáním do ignore listu![br][br] Současný počet osob, které to nepochopily: 7
ondra.holub+1
Stálý člen
22. 11. 2008   #15
-
0
-

Pokud je záměr, aby pole bylo v paměti bylo souvisle bez výplní, je potřeba udělat pole něčeho, co má velikost bajt, tedy např. uint8_t. Ale ke každému prvku se musí přistupovat přes ten union, čímž dostaneme zadarmo (udělá to překladač) postup, jak (např.) inkrementovat jenom část toho bajtu.

#include <stdio.h>

#include <stdint.h>

enum YesNo
{
NO = 0x0,
YES = 0xF
};

struct Xyz
{
unsigned data_:4;
unsigned yes_no_:4;
};

union Int4
{
struct Xyz xyz_;
uint8_t integer_;
};

#define Data(pole, index) ((union Int4*)(pole + index))->xyz_.data_
#define YesNo(pole, index) ((union Int4*)(pole + index))->xyz_.yes_no_

int main(void)
{
union Int4 i4a___[10]; // Toto je jenom pro ilustraci - budou tam vyplne
uint8_t i4a[10]; // Toto bude souvisle za sebou bajt po bajtu - to potrebujeme

printf("sizeof(i4a) = %d\n", sizeof(i4a___));
printf("sizeof(i4a) = %d\n", sizeof(i4a));

Data(i4a, 5) = 3;
YesNo(i4a, 5) = YES;

printf("5. prvek pole 0x%x\n\n", i4a[5]);

for (int i = 0; i < 20; ++i)
{
++Data(i4a, 5);
printf("5. prvek pole 0x%x\n", i4a[5]);
}

return 0;
}

Nahlásit jako SPAM
IP: 89.203.160.–
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, 82 hostů

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ý