delen in C

trix

Golden Member

hallo,

ik ben wat berekeningen in C aan het doen. nu kom ik er achter dat 0/1000 niet 0 is (wat je wel zou verwachten).
klopt dat ? en hoe doe je dat dan wel ?
tnx.

eigenwijs = ook wijs
Arco

Special Member

Moeilijk wat zinnigs te zeggen zonder code... :)
Er zou wel degelijk 0 uit een integer deling moeten komen...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
big_fat_mama

Zie Paulinha_B

Je bent toch niet met floats aan het stoeien? Dan wordt het
0.0/1000.0
Het overkomt me wel eens dat ik .0 moet toevoegen om float te forceren.

Verder sluit ik me (alweer :) ) helemaal aan bij @Arco. Toon eens de code, en de output? En misschien kun je het ruimere plaatje schetsen: wat dient er bereikt te worden?

hoe beter de vraag geschreven, zoveel te meer kans op goed antwoord
trix

Golden Member

het is een for loop:

c code:


for (Y_scan = 0; Y_scan < 37000; Y_scan = Y_scan + 1000)

verder op doe ik dan:

c code:


LTOY = (Y_scan / 1000) + 3; 

vul ik i.p.v. Y_scan gewoon een 0 in, dan gaat het wel goed (LTOY =3)

edit: Y_scan is gedeclareerd als een long.

eigenwijs = ook wijs
Arco

Special Member

Waarde van LTOY zou dus tussen de 3 en 40 moeten liggen.
Het zijn wel allemaal gewoon unsigned integer variabelen?

Edit: Waarom een long als je alleen positieve waardes gebruikt?

[Bericht gewijzigd door Arco op zaterdag 30 mei 2020 11:58:29 (23%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Tegenwoordig heb je handige online C compilers om dit soort dingetjes snel te kunnen testen.

https://onlinegdb.com/HkEQ0ikhI
LTOY = '39'

Persoonlijk houd ik liever de STDINT aan, dus uint32_t ect. Dat is altijd duidelijk en processor onafhankelijk.

PE2BAS
trix

Golden Member

ik heb een int geprobeerd, maar toen kon ik niet 37000 gebruiken maar wel b.v. 32000. daar trok ik de conclusie uit dat de int "signed" was, en ben over gestapt naar de "long".

edit: wat hardass zegt vind ik ook duidelijker, maar ik weet te weinig v/d materie en dus ook niet of ik dat ongestraft kan toepassen.

[Bericht gewijzigd door trix op zaterdag 30 mei 2020 12:03:47 (28%)

eigenwijs = ook wijs
Arco

Special Member

Compilers die ik gebruik hebben words voor 2 bytes en dwords voor 4 bytes unsigned...
Een signed 16 bit int gaat tot +/- 32767, een unsigned 16 bit int tot 65535

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Een int is in 'C' standaard een signed getal. Je moet expliciet 'unsigned int' declareren. Die long zal ook signed zijn.\

Maar dan nog, 0/N zal toch altijd 0 op moeten leveren, tenzij je floats gebruikt.

[Bericht gewijzigd door flipflop op zaterdag 30 mei 2020 12:23:14 (26%)

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Lucky Luke

Golden Member

Zou er ergens een instelling zijn dat delingen altijd als float gedaan worden? Maar dan nog, LTOY is een int (of long), dus zou alsnog omgezet moeten worden...

c code:


Unsigned int LTOY, Y_scan;

LTOY = (Y_scan / 1000UL) + 3; 

Wat krijg je er eigenlijk wel uit, als het geen 0 is?

Eluke.nl | handgetypt | De mens onderscheid zich van (andere) dieren door o.a. complexe gereedschappen en bouwwerken te maken. Mens zijn is nerd zijn. Blijf Maken. (Of wordt, bijvoorbeeld, cultuurhistoricus)

nul gedeeld door 1000 is gewoon nul. Dat is in C ook gewoon zo.
Ik heb een testprogramma geschreven:

code:


#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
   int a, b;
   a = 0;
   b = 1000;

   if (argc > 1)  a = atoi (argv[1]);
   if (argc > 2)  a = atoi (argv[2]);
   printf ("%d / %d = %d. \n", a, b, a/b);
}

en dat geeft gewoon het verwachte resultaat:

code:


% ./a.out
0 / 1000 = 0. 
% 

Update net even je LTOY code toegevoegd...

code:


void test_trix (void)
{
  int Y_scan, LTOY;
  for (Y_scan = 0; Y_scan < 37000; Y_scan = Y_scan + 1000) {
     LTOY = (Y_scan / 1000) + 3; 
    printf ("Y_scan = %d, LTOY = %d.\n", Y_scan, LTOY);
  }
}

En ook dat werkt conform verwachting.(begint bij 0 / 3 en eindigt met 36000 / 39 als laatste.)

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
trix

Golden Member

Wat krijg je er eigenlijk wel uit, als het geen 0 is?

41

[Bericht gewijzigd door trix op zaterdag 30 mei 2020 14:24:05 (31%)

eigenwijs = ook wijs
trix

Golden Member

ik post even een grotere stuk code. wellicht is het dan wat duidelijker, en mischien zien julie nog andere gekke dingen.

c code:


int X_scan				= 0;
long Y_scan				= 0;
int Y_bit				= 0;
int RAM_address			= 0;
int check_byte_1		= 0; // checked byte
int check_byte_2		= 0; // byte right check
int check_byte_3		= 0; // byte below check 
int check_byte_4		= 0; // corner bit check
int LTOX				= 0; // Left Top Out Y pos
int LTOY				= 0; // Left Top Out Y pos
int LTO_found			= 0; // we found the Left Top Out corner
int RTOX				= 0; // Right Top Out Y pos
int RTOY				= 0; // Right Top Out Y pos
int RTO_found			= 0; // we found the right Top Out corner
int tester1				= 0; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int tester2				= 0; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int tester3				= 0; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int control_is_ending	= 0; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int xx					= 1; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int yy					= 1; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int zz					= 1; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0); // Enable SPI, Master, set clock rate fck/128

uint8_t SPI_transfer(uint8_t data) // functie
{
	SPDR = data;
	while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
	return SPDR;
}

uint32_t address;

PORTA |= (1 << PINA0); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

for (Y_scan = 0; Y_scan < 37000; Y_scan = Y_scan + 1000)
{
	for (X_scan = 0; X_scan < 300; X_scan ++)
	{
	//	RAM_address = Y_scan + X_scan + 1;
		RAM_address = X_scan + 1;
		
		PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
		SPI_transfer(0b00000011);  // read data from memory
		address = RAM_address; // is address in ext. RAM 
		
		SPI_transfer((address>>16)); // address
		SPI_transfer((address>>8)); // address
		SPI_transfer((address)); // address
		
		SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM

		PORTG |= (1 << PING5); // make SS ext. RAM pin = 1
		
		check_byte_1 = SPDR; // 76543210		
	
	// below: if 2 neighbors bits are "1", check the next byte	
		if ((check_byte_1 == 192) || (check_byte_1 == 224) || (check_byte_1 == 240) || (check_byte_1 == 248) ||
		   (check_byte_1 == 252) || (check_byte_1 == 254) || (check_byte_1 == 255)) 
			{				
				PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
				SPI_transfer(0b00000011);  // read data from memory
				address = RAM_address + 1; // is address in ext. RAM from the byte right to the checked byte
				
				SPI_transfer((address>>16)); // address
				SPI_transfer((address>>8)); // address
				SPI_transfer((address)); // address
				
				SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM

				PORTG |= (1 << PING5); // make SS ext. RAM pin = 1
				
				check_byte_2 = SPDR; // 76543210		
		
				
		// below: if in the next byte also the same 2 neighbors bits are "1"		
				if ((check_byte_1 == 192)  && (check_byte_2 == 192))  { LTOY = (Y_scan / 1000) + 7; }
				if ((check_byte_1 == 224)  && (check_byte_2 == 224))  { LTOY = (Y_scan / 1000) + 6; }
				if ((check_byte_1 == 240)  && (check_byte_2 == 240))  { LTOY = (Y_scan / 1000) + 5; }
				if ((check_byte_1 == 248)  && (check_byte_2 == 248))  { LTOY = (Y_scan / 1000) + 4; }
				if ((check_byte_1 == 252)  && (check_byte_2 == 252))  { LTOY = (Y_scan / 1000) + 3; }
				if ((check_byte_1 == 254)  && (check_byte_2 == 254))  { LTOY = (Y_scan / 1000) + 2; }
				if ((check_byte_1 == 255)  && (check_byte_2 == 255))  { LTOY = (Y_scan / 1000) + 1; }
					
				if (LTO_found == 0) { LTOX = RAM_address; LTO_found = 1;	}
				
		
		// below: if bit #7 = "1"			
				if ((check_byte_1 == 128) && (check_byte_2 == 128))
				{
					PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
					SPI_transfer(0b00000011);  // read data from memory
					address = RAM_address + 1000; // is address in ext. RAM from the byte below the checked byte
					
					SPI_transfer((address>>16)); // address
					SPI_transfer((address>>8)); // address
					SPI_transfer((address)); // address
					
					SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM

					PORTG |= (1 << PING5); // make SS ext. RAM pin = 1
					
					check_byte_3 = SPDR; // 76543210
					
		// below: now we gonna check for the corner bit		
					if (check_byte_3 == 1)
					{
						PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
						SPI_transfer(0b00000011);  // read data from memory
						address = RAM_address + 1001; // is address in ext. RAM from the "corner byte"
						
						SPI_transfer((address>>16)); // address
						SPI_transfer((address>>8)); // address
						SPI_transfer((address)); // address
						
						SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM

						PORTG |= (1 << PING5); // make SS ext. RAM pin = 1
						
						check_byte_4 = SPDR; // 76543210
						
						if ((check_byte_4 == 1) && (LTO_found == 0))
						{
							 LTOX = X_scan; LTO_found = 1;
						}	
					}
				}	 						
		} // from: if ((check_byte_1 == 3.....................

// *****************************************************************************************************		
// *** NOW WE FOUND THE LTO CORNER, WE GONNA SEARCH FOR THE RTO CORNER *********************************
// *****************************************************************************************************

		if ((check_byte_1 == 0) && (LTO_found == 1) && (RTO_found == 0)) // this is the end of the window
		{			
			RTOX = RAM_address;
			RTOY = LTOY;
			RTO_found = 1;
		}
		
// *****************************************************************************************************
// *** NOW WE FOUND THE RTO CORNER, WE GONNA SEARCH FOR THE LTI_1 CORNER ********************************
// *****************************************************************************************************		
		
	} // from: (for (X_scan..............	
} // from: (for (Y_scan..............

PORTA |= (1 << PINA4); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

control_is_ending = 1;
#include "check_the_corner_bytes.h"

eigenwijs = ook wijs

LTOY is altijd nul, de variabele krijgt nooit een nieuwe waarde toegekend. Ik snap niet wat dat met delen te maken heeft.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
trix

Golden Member

jawel, in het stukje:

c code:


if ((check_byte_1 == 192)  && (check_byte_2 == 192))  { LTOY = (Y_scan / 1000) + 7; }
				if ((check_byte_1 == 224)  && (check_byte_2 == 224))  { LTOY = (Y_scan / 1000) + 6; }
				if ((check_byte_1 == 240)  && (check_byte_2 == 240))  { LTOY = (Y_scan / 1000) + 5; }
				if ((check_byte_1 == 248)  && (check_byte_2 == 248))  { LTOY = (Y_scan / 1000) + 4; }
				if ((check_byte_1 == 252)  && (check_byte_2 == 252))  { LTOY = (Y_scan / 1000) + 3; }
				if ((check_byte_1 == 254)  && (check_byte_2 == 254))  { LTOY = (Y_scan / 1000) + 2; }
				if ((check_byte_1 == 255)  && (check_byte_2 == 255))  { LTOY = (Y_scan / 1000) + 1; 
eigenwijs = ook wijs

Ja sorry. Ik was te snel.

In het kader van "misschien zien jullie nog wat"....

code:

    PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
    SPI_transfer(0b00000011);  // read data from memory
    address = RAM_address + 1; // is address in ext. RAM from the byte right to the checked byte

    SPI_transfer((address>>16)); // address
    SPI_transfer((address>>8)); // address
    SPI_transfer((address)); // address

    SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM

    PORTG |= (1 << PING5); // make SS ext. RAM pin = 1

    check_byte_2 = SPDR; // 76543210

is volgens mij het lezen van een byte uit een externe RAM.

Maak daar een functie van:

code:


    check_byte_2 = ram_read (RAM_address+1);

Dat maakt de code overzichtelijker omdat je in dit deel van de code niet bezig bent met "SPI hardware aansturen" maar gewoon met bytes uit ram halen.

Ohh... Ik zie dezelfde code nu al 3x terugkomen. De "interessante" code wordt daarmee zo al direct 33 regels korter en dus makkelijker te bevatten voor mensen.

Dan kan je zeggen dat het minder efficient is. Maar werkende code is VEEL belangrijker dan efficiente code. Mocht je echt denken dat het veel uitmaakt dat die code inline is dan kan je de compiler vragen om dat inderdaad te doen.

Op een CPU met een instructie cache (alles groter dan een AVR) is het trouwens al snel verstandig om WEL functies te gebruiken in zo'n geval als hier: nu gebruik je 3x zo veel I-cache als wanneer je een functie zou aanroepen. En omdat de cache niet onbeperkt is, loont het om je cache-footprint kleiner te houden. En zeker omdat je hier IO met externe dingen doet, zal het toch veel trager zijn dan dat de CPU kan. Dus ZEKER een reden om het in een functie te doen.

Dan nog een dingetje:

code:


#define RAM_CS_PORT PORTG
#define RAM_CS_PIN  PING5
#define ACTIVATE_RAM_CS()   RAM_CS_PORT &= ~_BV(RAM_CS_PIN)
#define DEACTIVATE_RAM_CS() RAM_CS_PORT |=  _BV(RAM_CS_PIN)
uint8_t read_ram(long addr) // Die long hier betekent dat je al een paar bugs gevonden hebt in je code! 
{
  uint8_t v;
  ACTIVATE_RAM_CS();
  SPI_transfer(0b00000011);

  SPI_transfer(addr>>16); // address
  SPI_transfer(addr>8); // address
  SPI_transfer(addr); // address
  v = SPI_transfer(0); // send dummy zero, chip returns data;
  DEACTIVATE_RAM_CS(); 
  return v;
}

Het lezen van het SPIDR nadat je de transfer hebt afgerond vind ik "vaag". Je gebruikt een SPI_transfer functie, die moet dan ook maar de ontvangen data teruggeven. de implementatie code die ik op het web vond doet dat ook inderdaad.

[Bericht gewijzigd door rew op zaterdag 30 mei 2020 16:03:32 (45%)

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
trix

Golden Member

inderdaat het lezen van een byte uit de ext. RAM

klopt, daar ben ik al mee bezig geweest. maar kreeg dat niet zo snel voor mekaar, en de prioriteiten lagen anders.

probleem was een beetje dat er in dat stukje wat je post al een functie zit nl.: SPI_transfer.

eigenwijs = ook wijs

Wat is er? Denk je dat je in een functie niet nog een functie kan aanroepen? Dat is jaren zestig computer-kunde. Dat kan dus ondertussen al meer dan vijftig jaar.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
trix

Golden Member

ja.....maar dan moet ik het ook nog kunnen :)

eigenwijs = ook wijs
trix

Golden Member

dat van het delen: LTOY/1000 is opgelost.
probleem was dat ik LTOY niet een malig schreef, maar iedere keer als de "loop" weer langs kwam.
stukje code veranderd:

c code:


if (LTO_found == 0)
{
	LTO_found = 1;
	LTOX = RAM_address;
					
	if ((check_byte_1 == 192)  && (check_byte_2 == 192))  { LTOY = (Y_scan / 1000) + 7; }
	if ((check_byte_1 == 224)  && (check_byte_2 == 224))  { LTOY = (Y_scan / 1000) + 6; }
	if ((check_byte_1 == 240)  && (check_byte_2 == 240))  { LTOY = (Y_scan / 1000) + 5; }
	if ((check_byte_1 == 248)  && (check_byte_2 == 248))  { LTOY = (Y_scan / 1000) + 4; }
	if ((check_byte_1 == 252)  && (check_byte_2 == 252))  { LTOY = (Y_scan / 1000) + 3; }
	if ((check_byte_1 == 254)  && (check_byte_2 == 254))  { LTOY = (Y_scan / 1000) + 2; }
	if ((check_byte_1 == 255)  && (check_byte_2 == 255))  { LTOY = (Y_scan / 1000) + 1; }					
}				
eigenwijs = ook wijs
trix

Golden Member

ik zou inderdaad zoals rew al terecht zegt gebruik willen maken van een functie.
ik maak hier over een nieuwe topic aan.

eigenwijs = ook wijs

Als 0/N 41 oplevert, dan weet je onmiddellijk dat je zelf iets fout doet. Dan kan geen fout vd compiler meer zijn. Dan zou het bv 0.00000000019 of zo moeten opleveren (al kan dat niet met een long natuurlijk).

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/