Konvertera flyttal till heltal (Integer) i C
Re: Konvertera flyttal till heltal (Integer) i C
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...
Eller för att uttrycka det på ett annat sätt, vi saknar information för att råda...
-
- Inlägg: 1400
- Blev medlem: 29 januari 2011, 21:06:30
- Ort: Lapplandet
Re: Konvertera flyttal till heltal (Integer) i C
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
Re: Konvertera flyttal till heltal (Integer) i C
Funderade lite...
Inte helt perfekt, men alltid något.
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;
}
//----------------------------------------------------------------
Re: Konvertera flyttal till heltal (Integer) i C
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.
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.
Re: Konvertera flyttal till heltal (Integer) i C
Nedan är Baronens kod förutom att jag ändrat uint32 till unsigned int osv..baron3d skrev:Funderade lite...
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;
}
//----------------------------------------------------------------
Verkar funka för de flesta heltal, men inte för t.ex. 0.01float = 4996b438
int = 1234567
Har inte testat avrundning mm...
provkört i https://www.jdoodle.com/c-online-compiler
-
- Inlägg: 6127
- Blev medlem: 27 februari 2006, 14:59:36
- Ort: Tranås (Jönköping)
Re: Konvertera flyttal till heltal (Integer) i C
Är flyttal verkligen ett problem idag då?
Om uC inte hanterar det, byt?
Om uC inte hanterar det, byt?
Re: Konvertera flyttal till heltal (Integer) i C
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.
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.
-
- Inlägg: 6127
- Blev medlem: 27 februari 2006, 14:59:36
- Ort: Tranås (Jönköping)
Re: Konvertera flyttal till heltal (Integer) i C
Missade det, ibland läser man igenom för fort helt enkelt.
-
- Inlägg: 6127
- Blev medlem: 27 februari 2006, 14:59:36
- Ort: Tranås (Jönköping)
Re: Konvertera flyttal till heltal (Integer) i C
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.
Har varit för att samma värde kan finnas över de olika modbustyperna så att säga.
Re: Konvertera flyttal till heltal (Integer) i C
Nej, det går inte att välja talformat, det är fixerat.
Re: Konvertera flyttal till heltal (Integer) i C
Men, VET man nåt om inom vilket intervall invärdena kan (eller ännu bättre garanteras) vara?jesse skrev:Verkar funka för de flesta heltal, men inte för t.ex. 0.01
Har inte testat avrundning mm...
Re: Konvertera flyttal till heltal (Integer) i C
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
Vissa kan naturligtvis avrundas, men inte alla.
Effektfaktorn till exempel, ligger mellan 0.00 - 1,00
Re: Konvertera flyttal till heltal (Integer) i C
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.
och anropa funktionen med resultat = float2int(data.x, 16);
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.
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;")Effektfaktorn till exempel, ligger mellan 0.00 - 1,00
och anropa funktionen med resultat = float2int(data.x, 16);
Re: Konvertera flyttal till heltal (Integer) i C
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.
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.
Re: Konvertera flyttal till heltal (Integer) i C
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.
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.