Float değişkeni Byte'lara bölme

Başlatan ehliseyf, 27 Temmuz 2016, 09:34:48

ehliseyf

4 Byte olan bir değişkeni byte byte almanın yöntemini öğretebilir misiniz. Kaydırma ile biraz düşündüm ama işin içinden çıkamadım. Aynı şekilde geri birleştirmenin de varsa güzel olur :)
Code'm mu oturturum !

ercan_t

merhaba

union ile yapabilirsin.

union
{
  float f;
  int i;
  unsigned char [4];
} u;

vs vs

kantirici

#2
Forumda detaylıca anlatımlar ve farklı yaklaşımlar var.

Union yapısı ile ulaşım en sade ve kolay ve anlaşılır olanı bana göre. Şurada da mantığından bahsedilmiş;

https://ozcanfatih.wordpress.com/2016/02/01/c-dilinde-union-yapisi-ve/

kimlenbu

ben makro kullanıyorum :

//degisken = 0x1234 olsun BYTE(degisken,0) yazinca 4 döndürüyor. BYTE(Degisken,0)= 9 yazýnca degisken 0x1239 oluyor.
#define BYTE(var,index) *(((unsigned char*)&var)+index)

mufitsozen

Alıntı yapılan: kimlenbu - 27 Temmuz 2016, 12:38:24
ben makro kullanıyorum :

//degisken = 0x1234 olsun BYTE(degisken,0) yazinca 4 döndürüyor. BYTE(Degisken,0)= 9 yazýnca degisken 0x1239 oluyor.
#define BYTE(var,index) *(((unsigned char*)&var)+index)


Cok kurnazca.


BYTE(Degisken,7)= 9 yazinca neler oluyor esas onu merak ettim  ;)

Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

ehliseyf

Alıntı yapılan: kimlenbu - 27 Temmuz 2016, 12:38:24
ben makro kullanıyorum :

//degisken = 0x1234 olsun BYTE(degisken,0) yazinca 4 döndürüyor. BYTE(Degisken,0)= 9 yazýnca degisken 0x1239 oluyor.
#define BYTE(var,index) *(((unsigned char*)&var)+index)

Hocam kullandım işime yaradı teşekkür ederim. Union yapısını anlayamadım
Code'm mu oturturum !

mir_as82

#6
Bu soruda, union yapıp For ile dolaşıp göndermek mi daha az makina kodu üretir yoksa, yukarıdaki makro kullanmak mı?örneğin biri diğerine göre % kaç daha az makina kodu üretir?

JKramer

#define satırı, derlemede değiştiriliyor; yani *(((unsigned char*)&var)+index) ne üretiyorsa o. Ama böyle şeyler kullanmamak lazım, mufitsozen'in gösterdiği gibi, "tehlikenin" farkına varın :).

kimlenbu

#8
Alıntı yapılan: mufitsozen - 27 Temmuz 2016, 14:42:48
Cok kurnazca.


BYTE(Degisken,7)= 9 yazinca neler oluyor esas onu merak ettim  ;)



Selamlar @mufitsozen hocam, "tehlikenin farkında mısınız" durumuna değinmeniz iyi oldu, kim bilir hafızada hangi bölgeyi değiştirecek, debug edene kadar insanın gözleri kör olur böyle bir durumda. Ben "index" 0,1,2,3 diye kendim belirttiğim için bir sorunla karşılaşmadım ama atıyorum döngü içinde kazara şu şekilde bir kullanım olursa dediğiniz tehlike ortaya çıkıyor

for (x=0;x<5;x++)
{
BYTE(degisken,x)=0;
}

JKramer

Bir de endian durumu var. Yarın biri gelip kodu big endian'da derlerse:
http://gph.is/1JSPK3Y

kimlenbu

Alıntı yapılan: JKramer - 28 Temmuz 2016, 10:38:06
Bir de endian durumu var. Yarın biri gelip kodu big endian'da derlerse:
http://gph.is/1JSPK3Y

korkudan kullandığım derleyicide böyle bir ayar var mı diye baktım, yokmuş neyse ki :D little endian kullanıyor.

F493

#11
Selam,

  Bir nokta dikkatimi çekti o nedenle yazmak istedim. Başlıkta float degişkeni byte lara bölme denmiş.

  Float değişken bir noktalı sayı tuttuğuna göre sağa sola shift işlemi yaptırmaz derleyici (<<, >>).

  Neden float tür kullanırız? Nedeni noktadan sonra değerleri de tutsun diye. Örneğin Adc den aldığımız değeri ekranda Voltaj olarak gösterecek ise 5.2v, 3.5v gibi float değişkene ihtiyaç duyarız. Buraya kadar aynı fikirde olduğumuzu düşünüyorum.

Asıl mesele yukarıdaki yöntemler veri kaybına neden olur yani 153.2 gibi bir değer için kullanırsanız 153 sonucunu elde edersiniz gibi. Yanlış mı düşünüyorum.
Ben de bazen yazılımda float değişkeni Eeprom'a kaydetmek için önce int'e sonra byte lara ayırmayı kullanıyorum ama bunu şu şekilde yapıyorum.

Sayımız 452.3 olsun ve bir kalibrasyon katsayısı olsun. Ekrandan ayarı yaptım ve bu değeri cihaz her açıldığında kullanmak için hafızaya kaydetmek için kaydet butonuna bastım.

float Kalibrasyon_Katsayisi = 452.3;
unsigned int KalibrasyonInt;


Bana noktadan sonra 1 hane yettiğinden    KalibrasyonInt = (unsigned int) (Kalibrasyon_Katsayisi * 10);

şekline dönüştürüyorum yani degeri 4523 haline dönüştürdüm. Şimdi byte lara ayırabilirim yani yukarıdaki yöntemleri kullabilirim diye düşünüyorum.


----------------------------------- En güvenli yöntem ise ------------------------------------------------

char buf[16];
float dataFloatTyte = 452.35655;


sprintf(buf, "%.1f", dataFloatTyte * 10);
// * 10 demek sayısı 10 ile çarp demek. Noktadan sonra 1 hane istiyoruz. İki hane isteseydik * 100 diyecektik.
// buf içinine 4523.56 değerini string olarak yazdık
result = atoi(buf);   // Bu fonksiyon 4523 degerini int olarak result değişkenine atar.
----------------------------------------------------------------------------------------------------------

Artık elimizde 4523 sayısı var. Bunu byte lara ayırabiliriz. Eeproma kaydedebiliriz.

Cihaz açılışında ise okuduğumuz bu degeri önce float'a dönüştürüp sonra 10' a bölersek 452.3 degerini elde ederiz.

Bu da denemek isteyenlere C kodu.
#include <stdio.h>
#include <stdlib.h>  // atoi icin gerekli.

float dataFloatTyte = (float)156.2654554;
int result;
char buf[16];

int main (void)
{
	
	printf("Ham float degeri = %f", dataFloatTyte);
	printf("\n------------------------------------\n");
	sprintf(buf, "%.1f", dataFloatTyte * 10);
	printf("sprintf sonucu = %s", buf);
	printf("\n------------------------------------\n");
	result = atoi(buf);
	printf("atoi sonucu = %d", result);

	// dataFloatTyte = dataFloatTyte >> 1; // error. Float türde bu işleme izin yok.

	getchar();

}


EDIT : Yazım hatası için yapılmıştır.  * 20 hatalı olmuş, *100 olarak düzeltildi.

Esen kalın.


mehmet

Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

JKramer

Float da olsa hafızada byte byte tutulmuyor mu? Float sayı kaç byte ise doğrudan alınabilir, parçalayıp toplamaya gerek yok.

yamak

#14
Alıntı yapılan: kimlenbu - 28 Temmuz 2016, 10:21:50
Selamlar @mufitsozen hocam, "tehlikenin farkında mısınız" durumuna değinmeniz iyi oldu, kim bilir hafızada hangi bölgeyi değiştirecek, debug edene kadar insanın gözleri kör olur böyle bir durumda. Ben "index" 0,1,2,3 diye kendim belirttiğim için bir sorunla karşılaşmadım ama atıyorum döngü içinde kazara şu şekilde bir kullanım olursa dediğiniz tehlike ortaya çıkıyor

for (x=0;x<5;x++)
{
BYTE(degisken,x)=0;
}
Macro'yu sonunda ';' ile yazarsak en azından derleyicinin hata vermesini sağlayıp @mufitsozen hocanın bahsettiği tehlikeyi önleyebiliriz.
#define BYTE(var,index) *(((unsigned char*)&var)+index);