It looks like on ATMega based boards, float
and double
are equivalent 32-bit (4-byte) data types.
However, on the Arduino Due, doubles
are 64-bit (8-byte) where floats
are 32-bit (4-byte), same as the ATMega boards.
I also saw one source on avr-gcc that listed double
as non-standard.
So, when writing code for ATMega based boards are floats
preferable to using doubles
, since that would make the code equivalent for Due boards? Or are doubles
preferable for any reason?
2 Answers 2
See avr-gcc
Deviations from the Standard
double
double is only 32 bits wide and implemented in the same way as float
when writing code for ATMega based boards ...
They are the same, therefore.
(Edited to add)
When writing code, is it then preferable to using one over the other?
I don't really understand your question. You asked about writing code for the ATMega based boards. Do you really mean, if you are writing code for the Due? The quick answer would be, on the Due, double takes twice the RAM, however it is over twice as precise - around 7.2 decimal digits for float compared to 15.9 for double. (I'm not sure about the speed, probably double would be slower, unless it is implemented in floating-point hardware - however I cannot see any reference to that on the AT91SAM3X8E datasheet).
See: https://en.wikipedia.org/wiki/Floating_point
If you want more precision (however slower and taking more RAM) then you could use double
- which won't make any difference on the ATmega based boards, but will on the Due.
As Edgar Bonet said:
I would use float so that anyone reading my code, who may not know about the non-standard AVR double, knows what precision to expect.
That makes quite a bit of sense.
I warn you though that "preferable" is subjective. It is close to asking "what is best"? To which the reply is: "best for what?"
-
On ATMega boards, yes, they are the same. If you then take the code to an Arduino Due, they are no longer the same if using
double
, but the same if usingfloat
. When writing code, is it then preferable to using one over the other? Why or why not?Ehryk– Ehryk2016年02月12日 16:30:04 +00:00Commented Feb 12, 2016 at 16:30 -
See amended reply.2016年02月12日 20:19:01 +00:00Commented Feb 12, 2016 at 20:19
-
Well, strictly speaking I'm only targeting ATMega architectures right now, I thought I was writing code that was consistent across all arduinos. I did not ask which was best, though I think I'm answering my own question in that
float
is more well known, a better cross-architecture description of the datatype, and consistent across more arduinos.Ehryk– Ehryk2016年02月14日 05:43:54 +00:00Commented Feb 14, 2016 at 5:43 -
Would it make more sense if I added "When writing Arduino code for an unknown board, is it then preferable to use one over the other?"Ehryk– Ehryk2016年02月14日 05:46:51 +00:00Commented Feb 14, 2016 at 5:46
-
I suppose. *shrug* - when dealing with boards which may have limited RAM and Flash, it isn't always possible to code generically.2016年02月14日 05:55:41 +00:00Commented Feb 14, 2016 at 5:55
Neither are preferable.
Unless your microcontroller has a hardware floating point unit using float or double results in huge overheads for your program.
So instead use integer mathematics whenever possible.
Instead of working in Volts, work in millivolts, for example.
However, if your MCU does have an FPU, and some modern more powerful ones do, then you should use the size of float or double that is native to the FPU. If it is a 32 bit FPU then use float. If it is a 64 bit FPU then you can use double.
-
do you have any actual benchmarks of the "huge overheads"? less efficient sure, but I've never really had it be a problem to use floating point on arduino.BrettFolkins– BrettFolkins2016年02月12日 17:34:17 +00:00Commented Feb 12, 2016 at 17:34
-
1
int a; void setup() { a = 1; } void loop() { a = a * 2; }
uses 482 bytes. Change theint
to afloat
it slmost doubles to 878 bytes. Even worse if you change the2
to2.0
, while it'sint
- you end up with 1086 bytes. Massive increases. And that's not even mentioning how long it takes to run. I'll do a crude benchmark.Majenko– Majenko2016年02月12日 18:42:18 +00:00Commented Feb 12, 2016 at 18:42 -
1Multiplying 1 by 2 until it exceeds 32768 (1, 2, 4, 8, 16, etc) with
int
takes 12 microseconds. Usingfloat
it takes 148 microseconds. That's more than ten times longer for just that one simple operation.Majenko– Majenko2016年02月12日 18:48:22 +00:00Commented Feb 12, 2016 at 18:48 -
Interestingly, multiplying an integer by
2.0
takes even longer - 208 microseconds. 17 times longer.Majenko– Majenko2016年02月12日 18:50:20 +00:00Commented Feb 12, 2016 at 18:50 -
Fixed point takes more ops than just integer multiply, and we should be comparing 32-bit values on both sides. in a test of float
(a*b)
and long(a*b/1000)
, as would be the case if you did operations in mV, floating point is faster. That's not calculating the extra high byte that's necessary for real fixed point, then again fixed point would benefit from an easier divisor. Addition will certainly remain faster in fixed point. I don't think float vs fixed is as clear cut as the arduino SE community makes it out to be.BrettFolkins– BrettFolkins2016年02月13日 01:40:55 +00:00Commented Feb 13, 2016 at 1:40
Explore related questions
See similar questions with these tags.
float
so that anyone reading my code, who may not know about the non-standard AVRdouble
, knows what precision to expect. But this is more personal preference than a hard rule (hence I do not consider it a "real" answer).