Hello,
I have always issues with calculation because I'm not frequently and professional user on Arduino...
In my last application I've to sum in a loop a very small value (between 0.000043333 to 0,0043333) to an increasing values like 110.4 (I'm interested only on first decimal in this case)
I'm going to implement something similari to the following code but I'm sure their Is something more elegant, any suggestion?
unsigned float a = 0;
unsigned float b = 110,3;
void setup() {
}
void loop() {
a = a + 0,000034
if (a >= 1) {
b = (int)a + b;
a = a - (int)a;
}
}
May I ask what the "small" values represent?
Often the problem is due to misrepresentation or inappropriate measurement.
If you measure the width of a hair in metres the value will be small. So choose suitable units.
What are you trying to do? Where are these numbers coming from? And like @sterretje said, you need to use the decimal dot, not the decimal comma, so 110.3 and not 110,3.
That is why I suggested a workaround, with one variable for whole numbers (110 in your example) and one variable for billionths (400004333 in your example).
@odometer yes, you did, but a solution to a problem is only useful if the OP understands the true nature of his problem, which @westfw kindly explained. Between the two of you, the OP has a workable answer AND the knowledge of why it is necessary.
Well, that's for sure the solution in case of mass production but I'm only building one piece.
this is a drops counter that should shows on a display the number of liters (after several days).
I measure a variable frequency while the drop dimension is the same.
Yes, that's the blocking point that brought me to rise my hand.
@odometer and @camsysca , thanks for suggestion, I think I'll go with the solution of two variables, one for the whole quantity and one for the billionths... the code of odometer is much more elegant than mine
Good suggestion. An unsigned 32 bit integer can total nanoliter drops up to 4.3 L, or more precisely, 4,294,967,295 nanoliters, without round off error.
And if that is not enough, then even an Arduino Uno can do calculations with uint64_t.
Suppose the drops are in picoliter, then the maximum is 18,446,744,073,709,551,615 picoliter, which is 18 million liters.
All the divide, multiply, add, subtract operations work on a uint64_t, but it can not be printed, because Serial.println() does not support it.
Here is an example with uint64_t:
// Increment 64 bits counter as fast as possible.
// Press the button to show the value.
// Forum: https://forum.arduino.cc/t/sum-of-float-variables-differing-by-10-8/1253425/18
// This Wokwi project: https://wokwi.com/projects/396560196465457153
uint64_t counter;
unsigned long previousMillis;
const unsigned long interval = 1000;
volatile bool flag;
void setup()
{
Serial.begin(115200);
Serial.println("Press button to show counter value");
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2),showNow,FALLING);
}
void loop()
{
counter++;
if(flag)
{
byte buffer[21];
buffer[20] = '\0';
uint64_t copy = counter;
for(int i=19; i>=0; i--)
{
int digit = copy % 10;
copy /= 10;
buffer[i] = (byte) (digit + '0');
}
Serial.println((char *)buffer);
flag = false;
}
}
void showNow()
{
flag = true;
}
Try it in Wokwi:
If my calculation is correct, then it takes 2Β½ million years to reach to the end with a Arduino Uno.
Modulus operator produces a value that fits well in byte type variable.
If int digit is declared as byte digit, then there is no need for this cast: (byte)(digit + '0').