Yaptigim matematik isleminde neden yanlis sonuc cikiyor??

Başlatan Digimensch, 12 Ocak 2011, 16:19:04

Digimensch

Hayret dogrusu ,
arkadaslar USB den gelen paket dizisinin ilk elemanini
#define data paket[0] 
int8 paket[64];
long sayi;
sayi=10*data+540;

yapip LCD'ye yazdirioyum.
printf(lcd_putc,"\Sonuc: %ld",sayi);

Sorunum su LCD'de bazen hatali sonuclar cikiyor.Örnegin gelen veri 100 oldugunda(bundan eminim cünkü gelen veriyide LCD gösteriyorum ...)
10*75+540=1290  cikmasi gerekirken 772 gibi sonuc cikiyor.

Bu sonuc nerden kaynaklaniyor , hatam nerde?
Ha birde gelen verilerin tutuldugu  int8 paket[64];
dizisini  long paket[64];
tipinde tanimladigim zamanda pic donuyor islem yapmiyor....
Not:USB'den veri  byte olarak geliyor bunuda hatirlatayim.
Acaba sorun gelen verinin tipindenmi,
yoksa yaptigim hesaplamadanmi yoksa LCD'den mi kaynaklaniyor?

eseneren

Seçim yapmak için durum hakkında bilgi sahibi olmak zorunda değilsin, sonucuna hazır olmak için durum hakkında kaygılanırsın.  http://bit.ly/gixfTk

Digimensch

#2
sorunu cözdüm arkadaslar
tek satir'da nedense yanlis hesap yapiyor pic.
yani söyle olunca hatali sonuc cikiyor.
sayi=10*data+540;



bende söyle yaptim bu sefer oldu.
sayi=data*10;
sayi=sayi+540;

hayret neden tek satirlik kodda dogru hesap yapmadi anlayamadim...??

Burak B

Büyük ihtimalle derleyici işlem sırasını karıştırıyordur. :)
Şöyle dene mesela
sayi=(10*data)+540;
"... a healthy dose of paranoia leads to better systems." Jack Ganssle

eseneren

her seferınde 772 vermsı enteresan,
10* (data +540) buda cevabı vermıyor baska bır ıs var ama cozemedım...
Seçim yapmak için durum hakkında bilgi sahibi olmak zorunda değilsin, sonucuna hazır olmak için durum hakkında kaygılanırsın.  http://bit.ly/gixfTk

Digimensch

Alıntı yapılan: senerenemre - 12 Ocak 2011, 21:18:10
her seferınde 772 vermsı enteresan,
10* (data +540) buda cevabı vermıyor baska bır ıs var ama cozemedım...

dostum sende mi denedin?
Sendede mi aynisi olyuor?
Hayret edilecek birsey...

fahri-

Bende de aynı tür problemler oluyordu. Sizin gibi bende işlemleri basitleştirip adımları çoğalttığımda doğru sonuca ulaşabiliyordum.  ;) Ama sebebini bilmiyorum.

Digimensch

Hayret o zaman bu CCS Compilerein bir BUG'u olsa gerek..

tmcone

Alıntı yapılan: Digimensch - 12 Ocak 2011, 19:38:16
sorunu cözdüm arkadaslar
tek satir'da nedense yanlis hesap yapiyor pic.
yani söyle olunca hatali sonuc cikiyor.
sayi=10*data+540;



bende söyle yaptim bu sefer oldu.
sayi=data*10;
sayi=sayi+540;

hayret neden tek satirlik kodda dogru hesap yapmadi anlayamadim...??

Kodunuzda data 8 bitlik bir değişken. Dolayısıyla data=100 için "10*data" ifadesinin sonucu  8 bitlik bir ara değişkende saklanacağından 232 (10*100 - 3*256) olacaktır. 540 + 232 = 772. Görüldüğü üzere matematiksel işlemde bir hata yok.  O halde hata nerede?

Derleyiciler matematiksel işlem yaparken önce tüm değişkenleri, işleme tabi tutulacak değişkenlerden boyutça büyük değişkenin türüne dönüşüm yaparlar. CCS C derleyicisinde varsayılan tamsayı türü diğer derleyicilerde olduğu gibi inttir; fakat ANSI C uyumlu derleyicilerden farklı olarak boyutu 8 bittir. Bu yüzden 10 * data ifadesinde 10, 8 bitlik bir değişken olarak değerlendirilecektir.Oysa Hitech PICC ve C18 derleyicilerinde 16 bitlik değişken kullanılarak işlem sonucu hesaplanacaktı. Bu durum CCS C de bu tür bir bug olduğu anlamına gelmez.

Doğru ifade,
sayi= (long)data*10 + 540;



Burak B

Bak bu byte mevzu gözümden kaçmış iyi yakalamışsın @tmcone.
"... a healthy dose of paranoia leads to better systems." Jack Ganssle

Digimensch

#10
Öyleyse derleyicinin aslinda
sayi= data*10 + 540; 
seklinde bir kullanimda data byte oldugu icin hata yok ama yinede dikkatli ol diye bir uyari falan vermesi gerekmiyormu?



RcALTIN

Alıntı yapılan: Digimensch - 13 Ocak 2011, 01:07:45
Öyleyse derleyicinin aslinda
sayi= data*10 + 540; 
seklinde bir kullanimda data byte oldugu icin hata yok ama yinede dikkatli oldu diye bir uyari falan vermesi gerekmiyormu?

aynı olayı c# da yapsaydık hata verir derlemezdi... ama ccs derliyor
byte a = 10;
ushort b = a * 10 + 540;

Cannot implicitly convert type 'int' to 'ushort'. An explicit conversion exists (are you missing a cast?)

byte a = 10;
ushort b = (ushort) (a * 10 + 540);

bilinçli tür dönüşümü

çünkü c#da işlem hesaplamaları int(32bit signed integer) e göre yapılıyor ve ushort(16bit unsigned integer) aralığı sonucu kapsayamıyor, sonucu almak için bilinçli tür dönüşümü yapmak gerekiyor. ccs de ise tmcone'un da değindiği gibi 8 bite göre yapılıyor ve programcının bunu bilerek matematiksel işlemler yapacağını varsayıyor olacak ki bir uyarı yada hata belirtmiyor; kısaca ccs bize kullandığınız derleyiciyi iyi tanıyın mesajı veriyor.  :)
KİMSEYİ ENGELLEDİĞİM YOK, ÖZEL İLETİ DEVRE DIŞI !

Digimensch

#12
Ama dikkat ederseniz ilk mesajimda
gelen veri byte tipinde ok .
ama su sekilde
#define data paket[0]  
int8 paket[64];

yaptigim icin gelen veri int8 tipndeki dizinin bir elemani artik.Öyleyse tip'de int8 olmus olmuyormu??

Simdi ben aynen söyle yaptigimda
int8 sayi;
sayi=10*data+540;
seklinde yaptigimda olmasi gerekmiyormu?  ama olmuyor

ve nitekim simdi denedim
sayi=((long)data*10)+540;  >>>> sonuc hatali

sayi int8 tipinde oldugu icin
sayi=((int8)data*10)+540; >>>>>sonuc yine hatali

su sekilde yapinca
      sayi=data*4;
      sayi=sayi+600; >>>>>>  sonuc dogru cikiyor !!!


RcALTIN

bende birşeyler denedim :
int x;
long y;

iken,

bilinçsiz dönüşüm :
x = 100;
y = ((long)x * 10) + 540;
printf(lcd_putc,"%ld",y);

yapınca, lcd de gördüğüm sonuç: 1540 = doğru

bilinçli dönüşüm :
y = 100;
x = ((int)y * 2) + 55;
printf(lcd_putc,"%u",x);

yapınca, lcd de gördüğüm sonuç: 255 = doğru

"int" yerine "int8" ; "long" yerine "int16" yazmak da olması gerektiği gibi sonucu etkilemiyor...

bilinçli dönüşümde y değişkenini 2 ile değilde 3 ile çarpsak ne olurdu ? sonuç 355 olurdu, oysa x değişkeni byte olduğundan 0-255 (256) değer alabilir, o yüzden sonuç, 355 mod 256 = 99 çıkar/çıkıyor...
KİMSEYİ ENGELLEDİĞİM YOK, ÖZEL İLETİ DEVRE DIŞI !

Digimensch

yani int  128
unsigned int 255'e kadar saniyorum byte  127'ye kadar deger alabiliyor degilmi Hocam??
Bunlarin alabilecekleri maximum degerleri bilmekte fayda var !!!
tesekkürler