Day of Week function not working as intended in Atmega8 - c

I have a C function that finds the Day of the week if given the complete date. This function works perfectly when I compile it on my laptop using gcc.
But when I compile the function for the Atmega8 using avr-gcc it gives the wrong answer. Could anyone help me figure out why?
Here's the C function
unsigned char *getDay(int year, int month, int day) {
static unsigned char *weekdayname[] = {"MON", "TUE",
"WED", "THU", "FRI", "SAT", "SUN"};
size_t JND = \
day \
+ ((153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5) \
+ (365 * (year + 4800 - ((14 - month) / 12))) \
+ ((year + 4800 - ((14 - month) / 12)) / 4) \
- ((year + 4800 - ((14 - month) / 12)) / 100) \
+ ((year + 4800 - ((14 - month) / 12)) / 400) \
- 32045;
return weekdayname[JND % 7];
}
For example, when I enter the date 01/01/2015 into the function on a laptop the function gives me the correct day of the week (Thursday) but on the atmega8 it gives me Monday.
Update:
The function sujithvm gave works! :D
But I still have no clue why the original function doesn't work on the avr. I tried uint32_t and int32_t. However, it looks like the day is always off by 3. Adding three to JND gives the correct day. That's a bit strange.

Try using this code
unsigned char *getDay(int y, int m, int d) {
static unsigned char *weekdayname[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
int weekday = (d += m < 3 ? y-- : y - 2 , 23 * m / 9 + d + 4 + y / 4 - y / 100 + y / 400) % 7;
return weekdayname[weekday];
}

Related

Calculation of countdown timer

How numerators and denominators of days, hours and minutes are calculated in this code, why modulus is calculated in numerator?
var countDownDate = new Date("Sep 5, 2018 15:37:25").getTime();
var x = setInterval(function() {
var now = new Date().getTime();
var distance = countDownDate - now;
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
document.getElementById("demo").innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
}, 1000);
Let me explain it line by line:
var countDownDate = new Date("Sep 5, 2018 15:37:25").getTime();
In the above line, you are getting the milliseconds for the date Sep 5, 2018 15:37:25 from Jan 1, 1970 (which is the reference date being used by getTime()
var now = new Date().getTime();
var distance = countDownDate - now;
The above two lines are simple. now gets the current time in milliseconds and distance is the difference between the two times (also in milliseconds)
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
The total number of seconds in a day is 60 * 60 * 24 and if we want to get the milliseconds, we need to multiply it by 1000 so the number 1000 * 60 * 60 * 24 is the total number of milliseconds in a day. Dividing the difference (distance) by this number and discarding the values after the decimal, we get the number of days.
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
The above line is a little tricker as there are two operations. The first operation (%) is used to basically discard the part of the difference representing days (% returns the remainder of the division so the days portion of the difference is taken out.
In the next step (division), 1000 * 60 * 60 is the total number of milliseconds in an hour. So dividing the remainder of the difference by this number will give us the number of hours (and like before we discard the numbers after decimal)
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
This is similar to how hours are calculated. The first operation (%) takes out the hours portion from difference and the division (1000*60) returns the minutes (as 1000 * 60 is the number of milliseconds in a minute)
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
Here the first operation (%) takes out the minutes part and the second operation (division) returns the number of seconds.
Note: You might have noticed that in every operation the original distance is used but the code still works fine. Let me give you an example (I am using difference instead of distance as this name makes more sense).
difference = 93234543
days = Math.floor(89234543 / (1000 * 60 * 60 * 24))
=> days = 1
hours = Math.floor((89234543 % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
(result of modulus operation is 6834543, and division is )
=> hours = 1
This is a very important operation to understand:
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
distance(difference) / (1000 * 60 * 60) returns 25 (hours). As you can see we have already got 1 day and 1 hour (25 hours) so distance % (1000 * 60 * 60) wipes out all of these 25 hours and then the division calculates the minutes and so on.

Understanding the math behind the code

I have a really basic and simple question but I am having problems with understanding this C code.
#define POLYNOMIAL(x) \
(((((3.0 * (x) + 2.0) * (x) - 5.0) * (x) - 1.0) * (x) + 7.0) * (x) - 6.0)
This definition is for this polynomial: 3x5+2x4-5x3-x2+7x-6
How can I convert this polynomial into the form shown in the #define? Is there any trick for this?
Your polynomial:
3x5 + 2x4 - 5x3 - x2 + 7x - 6
Can be rewritten successively:
(3x4 + 2x3 - 5x2 - x + 7) · x - 6
((3x3 + 2x2 - 5x - 1) · x + 7) · x - 6
(((3x2 + 2x - 5) · x - 1) · x + 7) · x - 6
((((3x + 2) · x - 5) · x - 1) · x + 7) · x - 6
This an expanded, or unrolled, Horner's Method loop. If the coefficients were expressed as an array:
double polynomial[] = { -6, 7, -1, -5, 2, 3 };
Then, the polynomial could be evaluated with this function:
double horners (double poly[], int terms, double x) {
double result = 0;
while (terms--) {
result = result * x + poly[terms];
}
return result;
}
Just add parenthesis and decrease out powers inside until you get to the last one, like this:
(3x^5)+(2x^4)-(5x^3)-(x^2)+7x-6
((3x^4)+(2x^3)-(5x^2)-x+7)x-6
(((3x^3)+(2x^2)-5x-1)x+7)x-6
((((3x^2)+2x-5)x-1)x+7)x-6
((((3x+2)x-5)x-1)x+7)x-6

epoch in seconds to MJD conversion in C

I wanted to convert the given time in epoch format to MJD (Modified Julian Day). But not getting exact MJD equivalent. I think missing some offset value.
#include <stdio.h>
#include <time.h>
#include <memory.h>
int get_mjd (int Y, int M, int D)
{
int L = 0, MJD = 0;
if ((M == 1) || (M == 2))
L = 1;
MJD = 14956 + D + (int)((Y - L) * 365.25) +
(int)((M + 1 + L * 12) * 30.60001);
return MJD;
}
int main(){
time_t start;
int mjd;
struct tm start_tm;
start = 1442286867; // Tue, 15 Sep 2015 03:14:27 GMT
memcpy(&start_tm, localtime(&start),sizeof(struct tm));
printf("year:%d\tmonth: %d\tday: %d\n",start_tm.tm_year,start_tm.tm_mon,start_tm.tm_mday);
mjd = get_mjd(start_tm.tm_year,start_tm.tm_mon, start_tm.tm_mday);
printf("mjd: %d\n",mjd);
return 0;
}
Output:
year:115 month: 8 day: 15
mjd: 57249
Expected mjd should is 57280
Please let me know what could be missing here.
If you don't need the date broken down into Gregorian calendar year/month/day values, there's a much simpler way.
double mjd(time_t epoch_time)
{
return epoch_time / 86400.0 + 40587;
}
The value 40587 is the number of days between the MJD epoch (1858-11-17) and the Unix epoch (1970-01-01), and 86400 is the number of seconds in a day.
Ref Modified Julian Day: Days since November 17, 1858
get_mjd() oddly references Y as years from 1900, yet M in the traditional 1 = January, 2 = February, etc.
get_mjd() works for years in the range 1898 to 2099, but fails outside that.
// For years from 1900, limited range
int get_mjd (int Y, int M, int D) {
int L = 0, MJD = 0;
if ((M == 1) || (M == 2))
L = 1;
MJD = 14956 + D + (int)((Y - L) * 365.25) +
(int)((M + 1 + L * 12) * 30.60001);
return MJD;
}
The following works over a much larger range or the Gregorian calendar.
M,D not limited to their usual range and does not need floating point math.
#define DaysPer400Years (365L*400 + 97)
#define DaysPer100Years (365L*100 + 24)
#define DaysPer4Years (365*4 + 1)
#define DaysPer1Year 365
#define MonthsPerYear 12
#define MonthsPer400Years (12*400)
#define MonthMarch 3
#define mjdOffset (678881 /* Epoch Nov 17, 1858 */)
static const short DaysMarch1ToBeginingOfMonth[12] = {
0,
31,
31 + 30,
31 + 30 + 31,
31 + 30 + 31 + 30,
31 + 30 + 31 + 30 + 31,
31 + 30 + 31 + 30 + 31 + 31,
31 + 30 + 31 + 30 + 31 + 31 + 30,
31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 + 31 };
int ymd_to_mjd_x(int year, int month, int day) {
year += month / MonthsPerYear;
month %= MonthsPerYear;
// Adjust for month/year to Mar... Feb
while (month < MonthMarch) {
month += MonthsPerYear; // Months per year
year--;
}
int d = (year / 400) * DaysPer400Years;
int y400 = (int) (year % 400);
d += (y400 / 100) * DaysPer100Years;
int y100 = y400 % 100;
d += (y100 / 4) * DaysPer4Years;
int y4 = y100 % 4;
d += y4 * DaysPer1Year;
d += DaysMarch1ToBeginingOfMonth[month - MonthMarch];
d += day;
// November 17, 1858 == MJD 0
d--;
d -= mjdOffset;
return d;
}
It was yet another off by one error. struct tm returns month with range 0-11.
I needed to +1 to tm_mon before using get_mjd(). Now it works!

Problems with my unix-epoch time converter

I wrote a simple function to fill three variables with the current year, month, and day.
However, for some reason it is not working correctly, and I can't seem to find the problem.
void getDate(int *year, int *month, int *date)
{
int epochTime,
monthLength,
functionYear,
functionMonth,
functionDate;
functionYear = 1970;
functionMonth = 1;
functionDate = 1;
epochTime = time(NULL);
while (epochTime > 1 * 365 * 24 * 60 * 60)
{
epochTime -= 1 * 365 * 24 * 60 * 60;
functionYear++;
}
monthLength = findMonthLength(functionYear, functionMonth, false);
while (epochTime > 1 * monthLength * 24 * 60 * 60)
{
printf("%d\n", epochTime);
epochTime -= 1 * monthLength * 24 * 60 * 60;
functionMonth++;
monthLength = findMonthLength(functionYear, functionMonth, false);
printf("functionMonth = %d\n", functionMonth);
}
while (epochTime > 1 * 24 * 60 * 60)
{
printf("%d\n", epochTime);
epochTime -= 1 * 24 * 60 * 60;
functionDate++;
printf("functionDate = %d\n", functionDate);
}
*year = functionYear;
*month = functionMonth;
*date = functionDate;
}
findMonthLength() returns an integer value which the length of the month it is sent. 1 = January, etc. It uses the year to test if it is a leap year.
It is currently April 3, 2013; however, my function finds April 15, and I can't seem to find where my problem is.
EDIT:
I got it. My first problem was that while I remembered to check for leap years when finding the months, I forgot about that when finding each year, which put me several days off.
My second problem was that I didn't convert to the local time zone from UTC
One problem could in this section:
while (epochTime > 1 * 365 * 24 * 60 * 60)
{
epochTime -= 1 * 365 * 24 * 60 * 60;
functionYear++;
}
Each iteration of this loop, a time in seconds corresponding to one normal year is subtracted. This does not account for leap years, where you need to subtract a time corresponding to 366 days.
For that section, you may want:
int yearLength = findYearLength(functionYear + 1);
while (epochTime > 1 * yearLength * 24 * 60 * 60)
{
epochTime -= 1 * yearLength * 24 * 60 * 60;
functionYear++;
yearLength = findYearLength(functionYear + 1);
}
with findYearLength(int year) being a function that returns the length in days of a given year.
One minor issue is that leap seconds are not accounted for. As only 35 of these have been added, that can be safely ignored in a calculation for a given day.
Why not use gmtime() or localtime() and be done with it? They return a structure with everything you need in it.
I made the complete solution based on yours, in Python. I hope it will help someone, someday. Cheers!
Use: getDate(unixtime)
def leapYear(year):
#returns True if the year is a leap year, return False if it isn't
if year % 400 == 0:
return True
elif year % 100 == 0:
return False
elif year % 4 == 0:
return True
else:
return False
def findMonthLength(year, month):
#returns an integer value with the length of the month it is sent.
#1 = January, etc. It uses the year to test if it is a leap year.
months1 = [0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
months2 = [0,31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if (leapYear(year)==True):
return months2[month]
else:
return months1[month]
def findYearLength(year):
#returns an integer value with the length of the year it is sent.
#It uses the year to test if it is a leap year.
if leapYear(year)==True:
return 366
else:
return 365
def getDate(epoch):
SECONDS_PER_YEAR = 0
SECONDS_PER_MONTH = 0
SECONDS_PER_DAY = 24 * 60 * 60
SECONDS_PER_HOUR = 60*60
SECONDS_PER_MIN = 60
epochTime = epoch
monthLength = 0
yearLength = 0
year = 1970
month = 1
day = 1
hour = 0
minu = 0
seg = 0
#Years
yearLength = findYearLength(year)
SECONDS_PER_YEAR = yearLength * SECONDS_PER_DAY
while (epochTime >= SECONDS_PER_YEAR):
epochTime -= SECONDS_PER_YEAR
year += 1
yearLength = findYearLength(year)
SECONDS_PER_YEAR = yearLength * SECONDS_PER_DAY
#Months
monthLength = findMonthLength(year, month)
SECONDS_PER_MONTH = monthLength * SECONDS_PER_DAY
while (epochTime >= SECONDS_PER_MONTH):
epochTime -= SECONDS_PER_MONTH;
month += 1
monthLength = findMonthLength(year, month)
SECONDS_PER_MONTH = monthLength * SECONDS_PER_DAY
#Days
while (epochTime >= SECONDS_PER_DAY):
epochTime -= SECONDS_PER_DAY;
day += 1
#Hours
while (epochTime >= SECONDS_PER_HOUR):
epochTime -= SECONDS_PER_HOUR;
hour += 1
#Minutes
while (epochTime >= SECONDS_PER_MIN):
epochTime -= SECONDS_PER_MIN;
minu += 1
#Seconds
seg = epochTime
print ("%d-%d-%d %d:%d:%d") % (year, month, day, hour, minu, seg)

Understanding CEILING macro use cases

I've found the following macro in a utility header in our codebase:
#define CEILING(x,y) (((x) + (y) - 1) / (y))
Which (with help from this answer) I've parsed as:
// Return the smallest multiple N of y such that:
// x <= y * N
But, no matter how much I stare at how this macro is used in our codebase, I can't understand the value of such an operation. None of the usages are commented, which seems to indicate it is something obvious.
Can anyone offer an English explanation of a use-case for this macro? It's probably blindingly obvious, I just can't see it...
Say you want to allocate memory in chunks (think: cache lines, disk sectors); how much memory will it take to hold an integral number of chunks that will contain the X bytes? If the chuck size is Y, then the answer is: CEILING(X,Y)
When you use an integer division in C like this
y = a / b
you get a result of division rounded towards zero, i.e. 5 / 2 == 2, -5 / 2 == -2. Sometimes it's desirable to round it another way so that 5 / 2 == 3, for example, if you want to take minimal integer array size to hold n bytes, you would want n / sizeof(int) rounded up, because you want space to hold that extra bytes.
So this macro does exactly this: CEILING(5,2) == 3, but note that it works for positive y only, so be careful.
Hmm... English example... You can only buy bananas in bunches of 5. You have 47 people who want a banana. How many bunches do you need? Answer = CEILING(47,5) = ((47 + 5) - 1) / 5 = 51 / 5 = 10 (dropping the remainder - integer division).
Let's try some test values
CEILING(6, 3) = (6 + 3 -1) / 3 = 8 / 3 = 2 // integer division
CEILING(7, 3) = (7 + 3 -1) / 3 = 9 / 3 = 3
CEILING(8, 3) = (8 + 3 -1) / 3 = 10 / 3 = 3
CEILING(9, 3) = (9 + 3 -1) / 3 = 11 / 3 = 3
CEILING(10, 3) = (9 + 3 -1) / 3 = 12 / 3 = 4
As you see, the result of the macro is an integer, the smallest possible z which satisfies: z * y >= x.
We can try with symbolics, as well:
CEILING(k*y, y) = (k*y + y -1) / y = ((k+1)*y - 1) / y = k
CEILING(k*y + 1, y) = ((k*y + 1) + y -1) / y = ((k+1)*y) / y = k + 1
CEILING(k*y + 2, y) = ((k*y + 2) + y -1) / y = ((k+1)*y + 1) / y = k + 1
....
CEILING(k*y + y - 1, y) = ((k*y + y - 1) + y -1) / y = ((k+1)*y + y - 2) / y = k + 1
CEILING(k*y + y, y) = ((k*y + y) + y -1) / y = ((k+1)*y + y - 1) / y = k + 1
CEILING(k*y + y + 1, y) = ((k*y + y + 1) + y -1) / y = ((k+2)*y) / y = k + 2
You canuse this to allocate memory with a size multiple of a constant, to determine how many tiles are needed to fill a screen, etc.
Watch out, though. This works only for positive y.
Hope it helps.
CEILING(x,y) gives you, assuming y > 0, the ceiling of x/y (mathematical division). One use case for that would be a prime sieve starting at an offset x, where you'd mark all multiples of the prime y in the sieve range as composites.

Resources