· 3 min read
Minus Seventeen Modulo Five Has Two Different Answers
17 mod 5 is 2 everywhere. −17 mod 5 is −2 in JavaScript, C and Java, and 3 in Python, Ruby and a spreadsheet. Both are right, and the difference is a real bug.

Front-end developer and tech writer at OneKitly
Web performance, file and document workflows, text tooling and developer utilities
Daniel is a front-end developer who writes about the things that pass through a working day: image and file formats, web performance, text and data wrangling, and the document workflows — signatures, PDFs, conversions — that sit between a file and the person waiting for it. He likes explaining technical trade-offs without the jargon, and says where a rule stops being technical and becomes legal.
Daniel starts from the specification — the format's own standard, the browser's documented behaviour — and checks it against the file in front of him rather than against the claim in a blog post. When a limit turns out to be legal rather than technical, he says which of the two he is describing.
Ranked by how many pages of this site link to them, not by traffic.
Guides published under this byline in each section. Each link opens the section in full, across all writers.
· 3 min read
17 mod 5 is 2 everywhere. −17 mod 5 is −2 in JavaScript, C and Java, and 3 in Python, Ruby and a spreadsheet. Both are right, and the difference is a real bug.
· 4 min read
Two 500 N/m springs end to end give 250 N/m; side by side they give 1,000. Under the same 50 N load that is 0.2 m of travel against 0.05 m, and 5 joules stored against 1.25.
· 4 min read
With an average of five events per interval, exactly three occur 14.0 % of the time, none at all 0.7 %, and ten or more 3.2 % — about once every 31 intervals. The distribution has one parameter, and it sets both the mean and the variance.
· 4 min read
The three digits are two figures and a count of zeros, in picofarads: 104 is 100 nF and 473 is 47 nF. The trap is 220, which is 22 pF — while a 220 pF part is marked 221.
· 3 min read
100, 220 and 330 µF in series come to 56.9 µF — less than the smallest. Put 100 µF and 1 µF in series and the total is 0.99 µF, while the small one carries 99 % of the voltage.
· 3 min read
10 mH with 100 µF resonates at 159.2 Hz. Double the capacitance and it falls to 112.5 Hz; to halve the frequency you have to quadruple a component, because both sit under a square root.
· 3 min read
1,000 Ω with 100 µF gives a time constant of 0.1 s. The capacitor is 63 % charged at that point, 95 % after three constants and 99.3 % after five — the last of which is the number that matters.
· 3 min read
25 million of revenue across 250 people is 100,000 each. Move fifty of them to a supplier and the same revenue reads 125,000 — a 25 % improvement in a productivity measure, with the same work being done.
· 3 min read
5,000 mAh drawn at 500 mA with 85 % efficiency runs for 8.5 hours instead of the arithmetic's 10. The same 15 % explains why a 5,000 mAh bank barely fills a 4,000 mAh phone once.
· 3 min read
Power lost as heat is current squared times resistance. Ten metres of 1.5 mm² extension lead has 0.233 Ω there and back: 23.3 W at 10 A, and 59.7 W at 16 A.
· 4 min read
2,000 words is 8 pages double-spaced, 4 single-spaced and 3.3 in a dense report layout. "How many pages" is a question about the layout, not about the text — and the 250-word page has a history.
· 4 min read
Delivery speed decides a talk's length more than the script does. At 170 words a minute the same text takes 7 min 04 s; at 110 it takes 10 min 55 s — and only one of those fits a ten-minute slot.
· 4 min read
Splitting a workbook writes one .xlsx per sheet, named after the tab. It carries the values across and not the formulas — which is the right default when the point is to send one department its own tab.
· 4 min read
JSON takes your header text as a key exactly as written. XML cannot — its names may not hold spaces, parentheses or a leading digit — so they are normalised, and knowing how prevents a surprise downstream.
· 4 min read
OpenDocument makes styles.xml optional. Several readers demand it and reject the whole document without it — "Cannot find file styles.xml in zip" on a file that is not broken.
· 4 min read
A cell can hold a formula and no cached result. A reader that skips empty cells throws the formula away with them — and says the file has none. One parsing option separates the two cases.
· 4 min read
Whitespace is the whole reason these tools exist. A row of blanks looks empty, is not empty to a strict test, and quietly survives every filter you apply after it.
· 4 min read
Twelve monthly reports can become twelve tabs or one table of twelve months. Only the second can be sorted and summed in one go — and it is the one where the header rows need handling.
· 4 min read
Course timetables, match fixtures, shift rotas and conference programmes all start life as a table. Four columns are enough to turn one into a file every calendar application can import.
· 3 min read
No stylesheet, no script, layout built from nested tables and styles written on every single tag. Knowing why explains what an exported HTML file will and will not look like.
· 3 min read
Same file, same parser, two outputs. The spreadsheet gets eight columns; the JSON gets the named time zone, the all-day flag and the recurrence rule as well.
· 3 min read
2.1 marks types without an equals sign, 3.0 is what everything reads, 4.0 writes some values as URIs — so a phone can arrive as tel:+33612345678, prefix included. Knowing which you have explains most import surprises.
· 3 min read
A contact can have several phone numbers and several addresses. The CSV joins them with a middle dot into one cell; the JSON keeps them as a list, which is the difference between a script that works and one that splits on a guess.
· 4 min read
Names, addresses and organisations are structured fields in a vCard. Flatten them into a spreadsheet and they read identically while losing the seams — which matters the moment you build a vCard back out of that spreadsheet.