Konvertera flyttal till heltal (Integer) i C

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av sodjan »

Att det inte är speciellt ovanligt betyder ju inte att den som Tomas använder har FPU.
Eller för att uttrycka det på ett annat sätt, vi saknar information för att råda... :-)
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av Mr Andersson »

Jo, det är ju sant. Fast som frågan är ställd (enklast och snabbast) utan detaljerad kravspec så är nog svaret: köp en mcu som har fpu :lol:
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1339
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av baron3d »

Funderade lite...
Inte helt perfekt, men alltid något.

Kod: Markera allt

//! Konverterar ett float till ett heltal
//! val_f = flytal som skall konverteras
//! opt   = options, val av faktor
sint16 float2int(sint32 val_f, uint16 opt) {
	sint32 tmp;
	uint32 sgn, exp, mant, sh;
	// sgn = signum
	// exp = exponent
	// mant = mantissa
	// sh = shift
		
	sgn  = val_f & 0x80000000;
	exp  = val_f & 0x7f800000; // 0111 1111 1000
	exp  = exp >> 23;
	mant = val_f;
	mant <<= 8; // *256
	if(exp) {
		// en extra etta
		mant |= 0x80000000;  	// 0000 0000 1000
	}
	exp -= 127;
	sh = 31 - exp;
	tmp = 1 << sh;	// faktor 1
	
	//if(opt == X01)  tmp *= 10  // faktor 0,1
	//if(opt == X10)  tmp /= 10  // faktor 10
	//if(opt == X100) tmp /= 100 // faktor 100
	
	mant += (uint32)tmp>>1; // avrundningstillägg
	mant /= (uint32)tmp;
	
	tmp = mant;
	
	if(sgn) return -tmp;
	return tmp;
}	
//----------------------------------------------------------------

Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45270
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av TomasL »

Nej, processorn har ingen FPU.
Hade den haft det, hade det varit enkelt.
Som Sodjan skrev, jag vill undvika och länka in ett flyttalsbibliotek.
Processorn är en PIC32MX, och att byta till en med flyttal är inte helt enkelt, då det kräver omdesign av kort samt byte av utvecklingsverktyg.
Och det finns inte på kartan, dessutom så skall det kunna fungera i befintlig utrustning.
samt det faktum att jag slått i taket med programminne på nuvarande.
När jag byter, i framtiden, så blir det väldigt radikalt, med en SOC i stället.
Nu ligger iofs framtiden nära, då jag jobbar med en ny SoC-baserad version.
Användarvisningsbild
jesse
Inlägg: 9234
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av jesse »

baron3d skrev:Funderade lite...
Nedan är Baronens kod förutom att jag ändrat uint32 till unsigned int osv..

Kod: Markera allt

#include<stdio.h>
int float2int(int val_f,  unsigned int opt);

union Data {
   int x;
   float f;
} data; 

int main() {
   data.f = 1234567;
   printf("float = %x\n\r", data.x);
   printf("int = %i", float2int(data.x, 0));
}
//! Konverterar ett float till ett heltal
//! val_f = flytal som skall konverteras
//! opt   = options, val av faktor
int float2int(int val_f,  unsigned int opt) {
	int tmp;
	unsigned int sgn, exp, mant, sh;
	// sgn = signum
	// exp = exponent
	// mant = mantissa
	// sh = shift
		
	sgn  = val_f & 0x80000000;
	exp  = val_f & 0x7f800000; // 0111 1111 1000
	exp  = exp >> 23;
	mant = val_f;
	mant <<= 8; // *256
	if(exp) {
		// en extra etta
		mant |= 0x80000000;  	// 0000 0000 1000
	}
	exp -= 127;
	sh = 31 - exp;
	tmp = 1 << sh;	// faktor 1
	
	//if(opt == X01)  tmp *= 10  // faktor 0,1
	//if(opt == X10)  tmp /= 10  // faktor 10
	//if(opt == X100) tmp /= 100 // faktor 100
	
	mant += (unsigned int)tmp>>1; // avrundningstillägg
	mant /= (unsigned int)tmp;
	
	tmp = mant;
	
	if(sgn) return -tmp;
	return tmp;
}	
//----------------------------------------------------------------
ger output:
float = 4996b438

int = 1234567
Verkar funka för de flesta heltal, men inte för t.ex. 0.01
Har inte testat avrundning mm...

provkört i https://www.jdoodle.com/c-online-compiler
FormerMazda
Inlägg: 6076
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av FormerMazda »

Är flyttal verkligen ett problem idag då?
Om uC inte hanterar det, byt?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45270
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av TomasL »

Läste du inte vad jag skrev?
Det är i dag en omöjlighet att byta uC, dessutom skall det vara kompatibelt med existerande system, i framtiden blir det naturligtvis en uC med FPU, men i existerande system finns det ingen FPU, och jag vill inte länka in ett tungt flyttals-bibliotek.
FormerMazda
Inlägg: 6076
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av FormerMazda »

Missade det, ibland läser man igenom för fort helt enkelt.
FormerMazda
Inlägg: 6076
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av FormerMazda »

Jag tror inte du har missat det, men finns kanske samma värde att läsa på annan modbustyp?
Har varit för att samma värde kan finnas över de olika modbustyperna så att säga.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45270
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av TomasL »

Nej, det går inte att välja talformat, det är fixerat.
Användarvisningsbild
rvl
Inlägg: 5780
Blev medlem: 5 april 2016, 14:58:53
Ort: Helsingfors

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av rvl »

jesse skrev:Verkar funka för de flesta heltal, men inte för t.ex. 0.01
Har inte testat avrundning mm...
Men, VET man nåt om inom vilket intervall invärdena kan (eller ännu bättre garanteras) vara?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45270
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av TomasL »

Vad jag hittat hittills är 0.0000 - 22000000,0000
Vissa kan naturligtvis avrundas, men inte alla.
Effektfaktorn till exempel, ligger mellan 0.00 - 1,00
Användarvisningsbild
jesse
Inlägg: 9234
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av jesse »

Det är ju väldigt enkelt att filtrera bort ovidkommande tal genom att kontrollera exponenten innan man börjar omvandla talet.

T.ex. om max inläst värde får vara 65535 så returnerar man error om exp > 243.
Om exp < 127 så betyder det att talet är mindre än 1 och då kan resultatet eventuellt avrundas till noll.
Effektfaktorn till exempel, ligger mellan 0.00 - 1,00
Då kan man ju addera t.ex. 16 till exp så får man ju ut 0 - 65536 med baronens kod. (det kan ju "opt" användas till... sätt opt till 16 och gör exp += opt; i början... ( efter raden "exp = exp >> 23;")
och anropa funktionen med resultat = float2int(data.x, 16);
guckrum
Inlägg: 1686
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av guckrum »

Avrundning genom att addera 0.5 före trunkering har den obehagliga
egenskapen att den oftare avrundar uppåt än nedåt, vilket innebär
att signalens medelvärde ökar efter avrundning. Speciellt illa är det
om man använder den för negativa tal också. Till exempel kommer
då en ren AC-signal att få en positiv DC-komponent efter avrundning,
och det finns applikationer där det inte är bra.

Enbart trunkering har samma effekt, medelvärdet minskar, eftersom
man alltid tar bort bitar med positiv vikt (vi pratar uteslutande tvåkomplement).

Default i IEEE-754 flyttalsaritmetik är att avrunda till närmsta jämna
heltal. Detta är en enkel och utmärkt metod som inte ger någon bias.
Man kan implementera den genom att ta beslut på de två mest
signifikanta bitarna som trunkeras bort.

Om det är viktigt att det blir rätt är det en bra ide' att använda beprövad kod.
Användarvisningsbild
hawkan
Inlägg: 2619
Blev medlem: 14 augusti 2011, 10:27:40

Re: Konvertera flyttal till heltal (Integer) i C

Inlägg av hawkan »

Om man tittar på 87.00 som var första talet som nämndes.
I IEEE-754 format är 2^6 * (1 + 1/4 + 1/16 + 1/32 + 1/64) = 87.0 (slå gärna på räknaren.)
Följer samma som koden som visats i tråden redan så inget konstigt.

Det man kan göra är att ta mantissans första 6 bittar och lägga till 2^6.
Mantissan för detta talet är 01011100000000000000000. Såååå

010111 + 1<< 6 = 87

Edit: slarvade lite. fixat.
Skriv svar