Unsigned long variable calculation error in Arduino

I am using Arduino IDE 1.8.5
my program is unix time calculator. But I don't want to use library.

unsigned long timecode=1648603414; // same calculation error for uint32_t
float hoursn=3600;
float temp3=0.00;

temp3=((timecode/hoursn)); 

Arduino, result is, 457945.37500
the result should be: 457945.3928 //I did calculate, on excel and calculator.

How can I calculate correctly?

Thanks

a float isn't an unsigned long. its time, compute using interger, not real, math.

float variables have a 6-7 digit accuracy. Switching to double will solve that problem but be aware that you need a 32 bit processor for that; on 8-bit processors like AVRs (e.g. Uno or Mega) doubles are treated as floats so it will not work in that case.

Use the advise by @madmark2150 and use unsigned integer calculations.

Good luck, it's a nice challenge :wink: There is more to time calculations than simple divisions; think about leap years (and the fact that the year 2000 1900 was not a leap year) and leap seconds.

Correction:
It should have been 1900. Can be divided by 4 but not 400.

1 Like

See the reference for the float data type for information on what kind accuracy that you can expect with floats and Arduino. Hint: it is not perfect.

1 Like

This is what I have found on 32-bit Arduino DUE.
457945.3928

Sketch:

void setup()
{
  Serial.begin(115200);
  unsigned long timecode = 1648603414; // same calculation error for uint32_t
  double hoursn = 3600;
  double temp3 = 0.00;

  temp3 = ((timecode / hoursn)); 
  Serial.print(temp3, 4);
}

void loop() {}
1 Like
void setup()
{
  Serial.begin(115200);
  unsigned long timecode = 1648603414; 
  const long hoursn = 3600;
  long hours  = timecode / hoursn; 
  long seconds  = timecode % hoursn; 
  ...

}

void loop() {}

Is a simple way to reduce to hours and seconds.
Try extending it to hh:mm:ss we

1 Like

you are right. Thanks
My program clock output.
HOURS : 457945
HOURS1 : 25
HOURS2 : 1
seconds : 1414
minute2 : 23
minute1 : 34
correct clock : 1:23:34

My program is,

void setup()
{
  Serial.begin(9600);
  unsigned long timecode = 1648603414; 
  const long hoursn = 3600;
  long hours  = timecode / hoursn; 
  long hours1  = hours % 60; 
  long hours2  = hours1 % 24;
  long seconds  = timecode % hoursn; 
  long minute2  = seconds / 60;
  long minute1  = seconds % 60;
  Serial.print("HOURS : " );Serial.println(hours);
  Serial.print("HOURS1 : ");Serial.println(hours1);
  Serial.print("HOURS2 : ");Serial.println(hours2);
Serial.print("seconds : ");Serial.println(seconds);
Serial.print("minute2 : ");Serial.println(minute2);
Serial.print("minute1 : ");Serial.println(minute1);
Serial.print("correct time : ");Serial.print(hours2);Serial.print(",");
Serial.print(minute2);Serial.print(",");
Serial.println(minute1);
}

void loop() {}

when calculating in excel,
I found for clock, 457945,392
The left side of this number was calculating the hour.
The right side was multiplied by 60 to give the minute.
the decimal place of the minute operation was multiplied by 60 for the second.
There was a float problem in Arduino. Therefore, it was not calculating correctly.
The way you show is more efficient for Arduino.
Thanks, Regards

arduino uno and nano make mistakes. I guess because it's not 32 bit.

serial monitor picture, in the your sketch.

image

Thanks, Regards.

This is what I have found on 32-bit Arduino DUE.
457945.3928

1 Like

Thanks for your alert. especially for the year 2000. Maybe I was just going to do a current and future calculation. There would be no need to go back. Maybe I wouldn't use it. But it's good to learn.
Mathematically, the calculations are correct in Excel, but sometimes it gives an error in the month transitions. I think it's from leap year calculation.
Still, I think I'm in a good place.
Regards

No, it makes a mistake because it is 32 bit floating point - it would have made the same mistake on a 64 bit x86 machine if you'd used the 32 bit IEEE-754 "float" data type.

Who told you that the year 2000 was not a leap year? Where are you getting your information from?

Sorry, you're right. It's 1900 that was not a leap year. I will correct my post.

The rule is that if the year is divisible by 100 and not divisible by 400, leap year is skipped. Again an attempt to approximate a real (the orbital period of the earth) with integer (years, months, days) math.

1 Like

I checked too. The year 2000 is a leap year. You've already made the correction.
Thanks

I guess that's right. It's just to see if it's divisible by 400 when it's a century.
But I also saw a program that tells whether it is divisible by 100.

How to Check Whether a Year is a Leap Year or Not?
A leap year has 366 days (the extra day is the 29th of February), and it comes after every four years. To check if a year is a leap year, divide the year by 4. If it is fully divisible by 4, it is a leap year. For example, the year 2016 is divisible 4, so it is a leap year, whereas, 2015 is not.

However, Century years like 300, 700, 1900, 2000 need to be divided by 400 to check whether they are leap years or not.

Here is a function which I have written, which I find useful for calendar stuff:

int days_in_month (int y, int m) {
  // Fourth, eleventh, ninth, and sixth,
  // thirty days to each we fix. 
  if ((m==4)||(m==11)||(m==9)||(m==6)) return 30; 
  // Every other, thirty-one,
  // except the second month alone,
  if (m!=2) return 31;
  // which hath twenty-eight, in fine,
  // till leap-year give it twenty-nine.
  if ((y%400)==0) return 29; // leap year
  if ((y%100)==0) return 28; // not a leap year
  if ((y%4)==0)   return 29; // leap year
  return 28; // not a leap year 
}

this example give error.
a function-definition is not allowed here before '{' token
for arduno uno.
I can't understand because I didn't use function type, before.
Can I use this example in arduino ide.
Also I understood the logic of the program. But I couldn't try.
thanks

Which example?

Post code, post error messages.

Spanish version goes close to this:

Thirty days has this November, with April, June and September
Twenty-eight days has only one, every other thirty-one

No provision for leap years, though

Treinta días tiene Noviembre, con Abril, Junio y Septiembre
De veintiocho sólo hay uno, los demás de treinta y uno

1 Like