Arduino not incrementing correctly

Hi all,

I am trying to write a code to calculate the position of the sun using my arduino, and I think I managed to have the code working, however, I have a certain variable in my code "n" that needs to incremented by a certain value each loop, I have this value at 0.0001, so the code for it is "n = n + 0.0001", and the arduino does increment, but not by 0.0001.

I figured that out when I found a significant error in the results at the end of the day, so I tracked back the code to find what was wrong, and I had the arduino display the values of "n" as it is incrementing it, and it was exactly 0.0001 when I had it display 4 decimal places, but when I had it display 7 decimal places, I noticed it is adding 0.0001016 instead of exactly 0.0001, that could be insignificant for a short time, but it gets accumulated and builds up to a HUGE error.

Does anybody know how to solve this?

here's my code: http://chopapp.com/#t62lqg6a

Sun_Position_Calculator___Draft_1.ino (2.54 KB)

increment integers, and then do this:

i = i+1
double n = i*.0001

You solv it by not using floating point variables but by using ints.
Only whe. You want to use that int in a floating point calculation do you divide by your scaling factor to get the number.
Floats are not a very accurate way of storing a number.

Thanks KeithRB for your reply

Do you mean have the "i" declared as an integer?

I am sorry I'm new to arduino and not quite familiar with the terminologies yet.

can you write exactly what should I define as integers? and would it be a problem when an integer is in a mathematical operation with a float?

Grumpy_Mike:
You solv it by not using floating point variables but by using ints.
Only whe. You want to use that int in a floating point calculation do you divide by your scaling factor to get the number.
Floats are not a very accurate way of storing a number.

Thanks Grumpy_Mike for your reply
But I thought floating variables can take more decimal places than integers, I thought integers can't take any decimal places!

I thought integers can't take any decimal places!

I sort of thought that was the definition of an integer .(that it is a whole number and not a float)

Mahmoud-elgeziry:
and it was exactly 0.0001 when I had it display 4 decimal places, but when I had it display 7 decimal places, I noticed it is adding ...0.0001016 instead of exactly 0.0001

On the Arduino double is the same as float. Float has around 7 digits of precision, so what you get is expected.

I have a Big Number library for the Arduino. It can be very precise but it is also slower:

Using that you set the number of digits after the decimal place you want (can be 100 or more). Warning, though the larger the number the slower and the more memory it takes.

Wow! That looks awesome, thanks a lot!

But I was trying to do it in the arduino code because it's a student project :confused:

You could also do what Grumpy_Mike suggests and use long type instead of float (you will get around 9 decimal digits of precision) but at least you won't get rounding errors like that. However you have to scale the result.

But I was trying to do it in the arduino code because it's a student project :confused:

That's Arduino code. It's just a library you add on. But if you don't want to use that use the "long" idea.

I know I will have to just include the library, but I mean I didn't come up with it, I will probably use it, but the teacher appreciates if we come up with everything in the code. Doesn't mind using others' work if cited tho

I could use Grumpy_Mike's idea, but I am not really sure how to do it, you guys expect a certain level of arduino experience that I don't have yet lol

you guys expect a certain level of arduino experience that I don't have yet lol

Not true. At least 25% of all new posts are Newbies with a post count of 1 and a karma count of 0 and a member registration date that is the same as the post date, meaning they know nothing. The question is how long does it take them to get from "nothing" to something ? It is not uncommon to see a post where a Newbie asks for the code and a schematic for his project. (could be someone in your class !)

Delta_G:

Mahmoud-elgeziry:
I could use Grumpy_Mike's idea, but I am not really sure how to do it, you guys expect a certain level of arduino experience that I don't have yet lol

Grumpy_Mike's idea isn't a programming thing. It's a math thing.

If I am dealing with distance, and I have distances between 0.00001 and 0.00100 meters then I have to deal with decimals right? Wrong. If I multiply every number by 100000 I can deal with distances instead in micrometers. I would have 10 to 1000 micrometers and now I can use a integer type variable.

Well you can do that with any kind of number, not just metric units. If I want 9 digits behind the decimal point I use a long int and multiply everything by 1 * 10^9. When I use that number I have to remember that I multiplied it. I'm more likely to change my interpretation of the number (thinking in terms of units) instead of ever converting anything to a float. I'd lose precision going to a floating point variable, they only get 7 digits of precision.

You have to think of precision not as numbers behind the decimal, but as the total number of digits involved. You can scale those numbers however you need to.

This makes a lot of sense, but my code involves lots of trigonometric operations, so I can't change 30 degrees to 30,000 millidegrees, because cos (30) is not equal cos (30000), or am I wrong? But since the "n" is not involved in any trig function, I could have the "n" to be a long integer as you suggest, and leave the "B" as a float? or would that make the arduino angry? to use a long integer to calculate a floating variable?

Thanks!

raschemmel:

you guys expect a certain level of arduino experience that I don't have yet lol

Not true. At least 25% of all new posts are Newbies with a post count of 1 and a karma count of 0 and a member registration date that is the same as the post date, meaning they know nothing. The question is how long does it take them to get from "nothing" to something ? It is not uncommon to see a post where a Newbie asks for the code and a schematic for his project. (could be someone in your class !)

So that practically makes me less than a newbie... perfect.

Mahmoud-elgeziry:
I have a certain variable in my code "n" that needs to incremented by a certain value each loop, I have this value at 0.0001, so the code for it is "n = n + 0.0001", and the arduino does increment, but not by 0.0001.
...
This makes a lot of sense, but my code involves lots of trigonometric operations, so I can't change 30 degrees to 30,000 millidegrees, because cos (30) is not equal cos (30000), or am I wrong? But since the "n" is not involved in any trig function, I could have the "n" to be a long integer as you suggest, and leave the "B" as a float? or would that make the arduino angry? to use a long integer to calculate a floating variable?

OK, so you deal in microdegrees (adding 100 instead of .0001). That way there aren't any rounding errors. Then to calculate the cosine, you do:

float foo = cos ((float) n / 1000000.0);

So it is converted back to degrees (not microdegrees) when you need it.

Computers save floating point numbers as binary fractions. (Sums of digits with values of 1/2, 1/4, 1/8, 1/16, 1/32, etc.)

They can only save values that can be represented exactly with sums of those power-of-2 fractions exactly. All other decimal values are approximations.

Decimal numbers have the same issue. You can't represent 1/3 exactly in decimal. It comes out to 0.3333333333333 (repeating.)

In binary floating point, 0.1, 0.01, 0.001, and so on are all repeating binary fractions that are only approximate.

The other posters are suggesting using values that are ten-thousandths, and then scaling the result back to a decimal before doing other calculations on it.

That works because whole numbers are not subject to the same kinds of approximation errors that fractions are. By scaling your values up into whole numbers, you avoid error at each step in your calculation, and only use floating point at the end. You should use long integer (long) instead of int, to avoid overflowing the largest value that can be stored in an int (which is I believe 32767 for ints on Arduino, and about 2 billion for a long (16 bit vs 32 bit signed integer values.)

Mahmoud-elgeziry:
Hi all,

I am trying to write a code to calculate the position of the sun using my arduino, and I think I managed to have the code working, however, I have a certain variable in my code "n" that needs to incremented by a certain value each loop, I have this value at 0.0001, so the code for it is "n = n + 0.0001", and the arduino does increment, but not by 0.0001.

I figured that out when I found a significant error in the results at the end of the day, so I tracked back the code to find what was wrong, and I had the arduino display the values of "n" as it is incrementing it, and it was exactly 0.0001 when I had it display 4 decimal places, but when I had it display 7 decimal places, I noticed it is adding 0.0001016 instead of exactly 0.0001, that could be insignificant for a short time, but it gets accumulated and builds up to a HUGE error.

Does anybody know how to solve this?

here's my code: ZURB - Chop

So that practically makes me less than a newbie... perfect.

It it what it is. We're here 24/7/365 and we're world-wide. There are as many time zones as there are countries on this forum. You can advance or learn as fast as you want. Heck, I was 0 for 0 (karma/post count) last October so I'm coming up on my 1 year anniversary. I don't think I'm going to get fountain pen set.....he he he XD

DuncanC:
Computers save floating point numbers as binary fractions. (Sums of digits with values of 1/2, 1/4, 1/8, 1/16, 1/32, etc.)

They can only save values that can be represented exactly with sums of those power-of-2 fractions exactly. All other decimal values are approximations.

Decimal numbers have the same issue. You can't represent 1/3 exactly in decimal. It comes out to 0.3333333333333 (repeating.)

In binary floating point, 0.1, 0.01, 0.001, and so on are all repeating binary fractions that are only approximate.

The other posters are suggesting using values that are ten-thousandths, and then scaling the result back to a decimal before doing other calculations on it.

That works because whole numbers are not subject to the same kinds of approximation errors that fractions are. By scaling your values up into whole numbers, you avoid error at each step in your calculation, and only use floating point at the end. You should use long integer (long) instead of int, to avoid overflowing the largest value that can be stored in an int (which is I believe 32767 for ints on Arduino, and about 2 billion for a long (16 bit vs 32 bit signed integer values.)

So I wrote a short code to test this, but I get the same "error"

long n = 2520000;

void setup()
{
Serial.begin(9600);
}

void loop()
{
n = n + 1;
float x = float (n)/10000;
Serial.println(x,7);
delay (2000);
}

and I still get the same problem, doesn't add "0.0001" exactly

and I still get the same problem, doesn't add "0.0001" exactly

Yes it does. read that excellent reply again.

Where the error comes in is in the conversion from the int n to the float x, not all values of n translate into exact values of x. That is the way computers work, it is not an error, it is a feature of floating point representation.

To see for yourself then print the value of n also.

Grumpy_Mike:

and I still get the same problem, doesn't add "0.0001" exactly

Yes it does. read that excellent reply again.

Where the error comes in is in the conversion from the int n to the float x, not all values of n translate into exact values of x. That is the way computers work, it is not an error, it is a feature of floating point representation.

To see for yourself then print the value of n also.

So is there any way to get a sequence:
252.0001
252.0002
252.0003

EXACTLY?

multiply it by 10000 and do n++, then devide by 10000 ?