Waarom gaat mijn afronding niet goed ?
13 berichten
• Pagina 1 van 2 • 1, 2
- FonzieBonzo
- Berichten: 118
- Geregistreerd: 01 Okt 2015, 11:54
- Woonplaats: Castricum
Waarom gaat mijn afronding niet goed ?
Ik ben een tijdje bezig geweest met het onderzoeken van een fout in mijn programma.
Uiteindelijk kwam het doordat ik het afronden tot 1 decimaal via het voorbeeld DeFloatFout deed, maar waarom gaat dat eigenlijk niet goed ?
Ik heb al op verschillende punten er haakjes tussen gezet maar het blijft afgerond worden tot hele getallen.
Gr,
Fonzie
cpp code
Uiteindelijk kwam het doordat ik het afronden tot 1 decimaal via het voorbeeld DeFloatFout deed, maar waarom gaat dat eigenlijk niet goed ?
Ik heb al op verschillende punten er haakjes tussen gezet maar het blijft afgerond worden tot hele getallen.
Gr,
Fonzie
cpp code
void setup() {
Serial.begin(9600);
float DeFloatFout = 1.54;
float DeFloatGoed = 1.54;
DeFloatFout = round(DeFloatFout * 10) / 10;
DeFloatGoed = round(DeFloatGoed * 10);
DeFloatGoed = DeFloatGoed / 10;
Serial.println(DeFloatFout); // geeft 1.00
Serial.println(DeFloatGoed); // geeft 1.50
}
Advertisement
Re: Waarom gaat mijn afronding niet goed ?
Ha ha, 1 april. Wacht even... het gaat echt verkeerd Jakkes Wat een smerige bug
Het kan alleen op die manier gaan als de round() functie een integer terug zou geven en de compiler de deling met integers gaat doen.
De round() functie zit in <math.h> en daar staat:
Maar in <Arduino.h> staat:
Ik heb het hele internet afgezocht, maar geen enkele officiële library heeft zo'n macro, alleen Arduino.
Het wordt op verschillende plaatsen gemeld, maar die bug zit er ondertussen nog steeds in.
De oplossing zou zijn om de #define in Arduino.h (dat is een 'macro') uit te schakelen door dit bovenaan je sketch te zetten:
Zulke problemen heb ik zelf trouwens niet, want ik gebruik floating point getallen voor floating point berekeningen. Een "10" is namelijk een integer en een "10.0" is een floating point getal.
Alleen al deze wijziging zorgt er voor dat het wel werkt:
Je sketch zou op deze manier geschreven kunnen worden:
Het kan alleen op die manier gaan als de round() functie een integer terug zou geven en de compiler de deling met integers gaat doen.
De round() functie zit in <math.h> en daar staat:
- Code: Alles selecteren
extern double round (double __x) __ATTR_CONST__;
#define roundf round
Maar in <Arduino.h> staat:
- Code: Alles selecteren
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
Ik heb het hele internet afgezocht, maar geen enkele officiële library heeft zo'n macro, alleen Arduino.
Het wordt op verschillende plaatsen gemeld, maar die bug zit er ondertussen nog steeds in.
De oplossing zou zijn om de #define in Arduino.h (dat is een 'macro') uit te schakelen door dit bovenaan je sketch te zetten:
- Code: Alles selecteren
#undef round
Zulke problemen heb ik zelf trouwens niet, want ik gebruik floating point getallen voor floating point berekeningen. Een "10" is namelijk een integer en een "10.0" is een floating point getal.
Alleen al deze wijziging zorgt er voor dat het wel werkt:
- Code: Alles selecteren
DeFloatFout = round( DeFloatFout * 10.0) / 10.0;
Je sketch zou op deze manier geschreven kunnen worden:
- Code: Alles selecteren
// Arduino IDE 1.81 with Arduino Uno
// Undefine the round macro in Arduino.h because that is a bug.
#undef round
void setup()
{
Serial.begin(9600);
float DeFloatFout = 1.54;
DeFloatFout = round( DeFloatFout * 10.0) / 10.0;
Serial.println(DeFloatFout);
float DeFloatGoed = 1.54;
DeFloatGoed = round(DeFloatGoed * 10.0);
DeFloatGoed = DeFloatGoed / 10.0;
Serial.println(DeFloatGoed);
float myFloat = 1.45;
Serial.println(myFloat,1); // Serial.print does rounding itself
}
void loop()
{
}
- FonzieBonzo
- Berichten: 118
- Geregistreerd: 01 Okt 2015, 11:54
- Woonplaats: Castricum
Re: Waarom gaat mijn afronding niet goed ?
Oh gelukkig maar want ik zoek natuurlijk eerst de fout bij mezelf
Dat is dan wel een slordige bug idd. Zeker als het al een tijdje bekend is.
Of zullen ze het niet meer durven op te lossen omdat systemen/formules rekenen op deze bug ?
In ieder geval dank voor de uitleg, is snap nu ook waar het fout gaat....
Gr,
Fonzie
Dat is dan wel een slordige bug idd. Zeker als het al een tijdje bekend is.
Of zullen ze het niet meer durven op te lossen omdat systemen/formules rekenen op deze bug ?
In ieder geval dank voor de uitleg, is snap nu ook waar het fout gaat....
Gr,
Fonzie
Re: Waarom gaat mijn afronding niet goed ?
Issue gemaakt: https://github.com/arduino/Arduino/issues/6098.
Maar ik heb er weinig vertrouwen in dat er iets mee gedaan wordt.
Probeer maar niet om er een "intelligente" reden voor te verzinnen dat het er nog steeds in zit, want voor zo'n bezopen belachelijk domme bug bestaat natuurlijk geen goede reden.
Een floating point library hoort onder alle omstandigheden betrouwbaar en voorspelbaar te zijn. Daar is veel moeite voor gedaan, en het is volgens een bepaalde standaard. De macro in "Arduino.h" gaat er zomaar iets anders van maken. Iemand die de floating point om zeep helpt heeft echt geen benul van programmeren. Des te meer ik er over nadenk, des te slechter ik het vind dat er zo iets in is geslopen.
Dankjewel dat je een duidelijk voorbeeld gaf, zo kwam ik snel bij het probleem. Eigenlijk zou Arduino je geld moeten geven voor het vinden van zo'n bug Dat zit er met Open Source helaas niet in.
Maar ik heb er weinig vertrouwen in dat er iets mee gedaan wordt.
Probeer maar niet om er een "intelligente" reden voor te verzinnen dat het er nog steeds in zit, want voor zo'n bezopen belachelijk domme bug bestaat natuurlijk geen goede reden.
Een floating point library hoort onder alle omstandigheden betrouwbaar en voorspelbaar te zijn. Daar is veel moeite voor gedaan, en het is volgens een bepaalde standaard. De macro in "Arduino.h" gaat er zomaar iets anders van maken. Iemand die de floating point om zeep helpt heeft echt geen benul van programmeren. Des te meer ik er over nadenk, des te slechter ik het vind dat er zo iets in is geslopen.
Dankjewel dat je een duidelijk voorbeeld gaf, zo kwam ik snel bij het probleem. Eigenlijk zou Arduino je geld moeten geven voor het vinden van zo'n bug Dat zit er met Open Source helaas niet in.
- FonzieBonzo
- Berichten: 118
- Geregistreerd: 01 Okt 2015, 11:54
- Woonplaats: Castricum
Re: Waarom gaat mijn afronding niet goed ?
Jammer van het geld maar misschien het belangrijkste, wat wij in ons leven ooit nog gaan doen we zullen nu in de hemel terecht komen
Wat ik alleen nog niet snap (en ik wil het snappen) waarom het wel goed gaat als ik het op deze manier vertel :
cpp code
Voor de round() die intern een integer gebuikt zou die .0 toch niet uit mogen maken?
Gr,
Fonzie
Wat ik alleen nog niet snap (en ik wil het snappen) waarom het wel goed gaat als ik het op deze manier vertel :
cpp code
DeFloatFout = round( DeFloatFout * 10.0) / 10.0;
Voor de round() die intern een integer gebuikt zou die .0 toch niet uit mogen maken?
Gr,
Fonzie
Re: Waarom gaat mijn afronding niet goed ?
Een "10" in de code is een integer.
Een "10.0" in de code is een float.
Wanneer de compiler een float en integer ziet, dan maakt de compiler er een float berekening van.
Wanneer de compiler een integer en een integer ziet, dan maakt de compiler er een integer berekening van.
Dus als ik het tot het bare minimum reduceer, dan is dit al voldoende:
Maar waarom half werk doen
Ik gebruik niet alleen "10.0" voor de compiler, maar ook om mezelf er aan te herinneren dat het een floating point berekening is.
Hieronder een voorbeeld van hoe het vooral niet moet:
Zie je die "( i / j )", die staat tussen haakjes en wordt dus eerst uitgevoerd. Die berekening doet de compiler met integers, pas daarna de "(f * " is vermenigvuldigen met een float en dan wordt het pas een float berekening.
Voorkomen is beter dan genezen.
Een "10.0" in de code is een float.
Wanneer de compiler een float en integer ziet, dan maakt de compiler er een float berekening van.
Wanneer de compiler een integer en een integer ziet, dan maakt de compiler er een integer berekening van.
Dus als ik het tot het bare minimum reduceer, dan is dit al voldoende:
- Code: Alles selecteren
DeFloatFout = round( DeFloatFout * 10) / 10.0;
Maar waarom half werk doen
Ik gebruik niet alleen "10.0" voor de compiler, maar ook om mezelf er aan te herinneren dat het een floating point berekening is.
Hieronder een voorbeeld van hoe het vooral niet moet:
- Code: Alles selecteren
// Arduino IDE 1.81 with Arduino Uno
// The "#undef round" removes the round() macro in Arduino.h
#undef round
void setup()
{
Serial.begin( 9600);
Serial.println(F( "Example how NOT to mix integer and float"));
int i = 50;
int j = 3;
float f = 12.5;
float g = 1.085E+6;
float result1 = g * (f * ( i / j ));
float result2 = g * (f * ( float(i) / float(j)));
Serial.println( result1);
Serial.println( result2);
}
void loop()
{
}
Zie je die "( i / j )", die staat tussen haakjes en wordt dus eerst uitgevoerd. Die berekening doet de compiler met integers, pas daarna de "(f * " is vermenigvuldigen met een float en dan wordt het pas een float berekening.
Voorkomen is beter dan genezen.
Laatst gewijzigd door Koepel op 20 Mrt 2017, 20:57, in totaal 1 keer gewijzigd.
- nicoverduin
- Berichten: 5043
- Geregistreerd: 13 Mei 2013, 20:57
- Woonplaats: Heemskerk
Re: Waarom gaat mijn afronding niet goed ?
nou daar heb ik ook niks aan als anti gelovige:)FonzieBonzo schreef:Jammer van het geld maar misschien het belangrijkste, wat wij in ons leven ooit nog gaan doen we zullen nu in de hemel terecht komen
Re: Waarom gaat mijn afronding niet goed ?
fons begin eerst eens met variabelen maar 1 keer te gebruiken, dat is simpel en voorkomt problemen met int,float etc.
verder heeft koepel natuurlijk wel gelijk, de compiler weet best hoe het moet als je het hem ook maar netjes verteld.
verder heeft koepel natuurlijk wel gelijk, de compiler weet best hoe het moet als je het hem ook maar netjes verteld.
paul deelen
shooter@home.nl
shooter@home.nl
- FonzieBonzo
- Berichten: 118
- Geregistreerd: 01 Okt 2015, 11:54
- Woonplaats: Castricum
Re: Waarom gaat mijn afronding niet goed ?
Ok ik snap het nu, thanks all !
Gr,
Fonzie
Gr,
Fonzie
Re: Waarom gaat mijn afronding niet goed ?
Mijn "issue" heeft een reactie: https://github.com/arduino/Arduino/issues/6098#issuecomment-288371069
[EDIT] Hij zegt nu 'sorry'. Er wordt naar gekeken
[EDIT] Hij zegt nu 'sorry'. Er wordt naar gekeken
13 berichten
• Pagina 1 van 2 • 1, 2
Wie is er online?
Gebruikers in dit forum: Geen geregistreerde gebruikers en 2 gasten