Happy (Not Really?) Pi Day!
John Colagioia Originally published at john.colagioia.net on ・5 min read
Far worse than arguments over lunar holidays is that everybody gets Pi Day wrong. Everybody is lying to you. It was on the fifth. You can trust me. I don't have an agenda like they do.
(Feel free to check out the original version of this post, too.)
Bear with me. This may sound like an unhinged rant (and...OK, yes, it totally is), but it's all in service of a legitimate programming technique later on. I promise!
So, why is March 5th correct but March 14th allegedly wrong? Because this is about math. If we accept that the whole number three (3) is counting months to give us March, then we have an irrational number left over, 0.141592654…
Sure, we could read digits and pretend that they represent days to pull off fourteen like a follower, but there’s a few problems with that.
- This is inconsistent with the interpretation of whole numbers.
- If fourteen (14) is legitimate, then why isn’t one (1) correct, instead?
- The answer relies on representing π as a decimal fraction; that is, a base-10 number where the fractional part is represented as the numerator out of some 10^{n}. A few missing or extra fingers and the date changes.
- The remainder much past the day isn’t very useful. Fifteen (15) could conceivably be 3pm, but we don’t have enough minutes in an hour to fit ninety-two (92), and nine (9) would be yet another rule change, so there is no such thing as “Pi Time” in this scheme.
- If we changed the number of digits taken per position, we would unfairly skew the distribution of days/hours/minutes/seconds.
That’s terrible math for a day that’s about a mathematical thing, right?
So, what’s the right way to do this? If the whole number is the number of months to count, then the fractional part should be the fraction into that month. So, we get…
Remaining | Action | Result/Reason |
---|---|---|
3.141592654 | Subtract 3 | 3 -> March |
0.141592654 | Multiply by 31 | Days in March |
4.389372274 | Subtract 4 | 4 + 1 -> Day of Month, fixing zero-offset |
0.389372274 | Multiply by 24 | Hours in a day |
9.344934576 | Subtract 9 | 9 -> 9am |
0.344934576 | Multiply by 60 | Minutes in an hour |
20.69607456 | Subtract 20 | 20 -> 9:20am |
0.69607456 | Multiply by 60 | Seconds in a minute |
41.7644736 | Subtract 41 | 41 -> 9:20:41am |
0.7644736 | N/A | Fraction of a second |
By this method, which is really just changing the radix (fancy term for "base") of the original number (π) to a mixed-radix system, we can drill down to whatever level of precision we need, yielding March 5th, 9:20:41.7644736 am. We have a consistent interpretation that works regardless of the radix we use to represent π to an arbitrary precision. (See more about this, below.)
You've been asked to wait an extra week for baked goods. Wake up, π-ple!
Better than that—for very niche definitions of “better,” obviously—this works for any physical constant, no matter how big or small, with only scientific notation and uneven distribution across the calendar requiring any subjective judgment.
In fact, let’s write some code to do that for us:
if (process.argv.length < 3) {
console.error("We need a number to work this out.");
return;
}
const arg = process.argv[2];
let n = Number(arg);
if (arg !== n.toString()) {
console.error("The argument needs to be a number.");
return;
}
if (n < 1 || n >= 13) {
// We could scale the number, instead of complaining
console.error("Until we add scaling code, the number needs to");
console.error("be at least 1 and less than 13.");
return;
}
let date = new Date();
// Harvest the month.
const nMonth = Math.trunc(n);
// The zeroth day of the next month is the last day of the
// previous month.
const daysInMonth = new Date(date.getYear(), nMonth, 0).getDate();
date.setMonth(nMonth - 1);
n -= nMonth;
n *= daysInMonth;
// Harvest the day.
const dayOfMonth = Math.trunc(n);
date.setDate(dayOfMonth + 1);
n -= dayOfMonth;
n *= 24;
// Harvest the hour.
const hourOfDay = Math.trunc(n);
date.setHours(hourOfDay);
n -= hourOfDay;
n *= 60;
// Harvest the minute.
const minuteOfHour = Math.trunc(n);
date.setMinutes(minuteOfHour);
n -= minuteOfHour;
n *= 60;
// Harvest the second.
const secondOfMinute = Math.trunc(n);
date.setSeconds(secondOfMinute);
n -= secondOfMinute;
console.log(date.toString());
console.log(`${n} of a second remaining.`);
It’s mildly redundant, but refactoring—like extracting the next-most-significant number—would only make the process less clear, I think.
But now that we have code, we might as well go nuts and start creating a whole calendar, right?
Constant | Holiday |
---|---|
Plastic number ρ | Sat Jan 11 2020 01:35:24 |
√2 | Mon Jan 13 2020 20:10:29 |
ψ | Wed Jan 15 2020 10:23:05 |
ϕ | Mon Jan 20 2020 03:49:02 |
√5 | Fri Feb 07 2020 20:18:11 |
e | Fri Feb 21 2020 19:55:26 |
c | Sat Feb 29 2020 22:33:19 |
π | Thu Mar 05 2020 09:20:41 |
Planck Time | Wed May 13 2020 03:05:17 |
h | Fri Jun 19 2020 18:46:13 |
G | Sun Jun 21 2020 05:29:49 |
α | Fri Jul 10 2020 05:13:49 |
ε_{0} | Thu Aug 27 2020 11:30:56 |
Apéry’s constant ζ(3) | Tue Dec 01 2020 15:18:12 |
μ_{0} | Fri Dec 18 2020 13:22:47 |
I mean, if it’s worth celebrating a “nerd holiday” at all (spoiler alert: it very much is not…), it’s surely worth overthinking the holiday! I can’t believe we all missed c Day. It was a Leap c Day, too!
Bonus: Change of Base
Now that we’ve done all that admittedly-weird work, we now have a much simpler algorithm to change the radix of numbers than is generally taught. All those times in the code where we multiply and yank off the whole number are the key. For integers, we need to…
- While the number (N) is greater than one (or less than negative one)…
- Divide the number N by the desired radix.
- While the number N is between negative one and one…
- Multiply the number N by the desired radix.
- Subtract the integer part of N from N, using that as the next significant digit.
We need 1234_{(10)} in…let’s say base-7? Repeatedly divide by 7 to get 176.285714286, 25.183673469, 3.597667638, and 0.51395252 and then start multiplying back up…
Digit | Fraction Remaining |
---|---|
3 | 0.597667638 |
4 | 0.183673469 |
1 | 0.285714286 |
2 | 0 |
So, 1234_{(10)} = 3412_{(7)}, in just a handful of steps! And since it looks like this whole Pi Day rant was all just an extended joke used as a sneaky excuse to teach some fringe-use math, I guess code to do this—and figuring out how to deal with a non-integer value or radix—can be safely left as an exercise to the reader…
π
Credits : The header image is Pi by an anonymous PxHere photographer, available under the CC0 1.0 Universal Public Domain Dedication.
A social network 100% devoted to making you a better coder?
Join DEV Now
Open source
Free forever
Level up every day
🔥