Holy cow, I wrote a book!
The Windows calculator percent sign works the same way as those
cheap pocket calculators (which are often called four-function calculators
even though they have around six function nowadays).
What you first have to understand is that the percent key on those
pocket calculators was
not designed for mathematicians and engineers.
It was designed for your everyday person doing some simple calculations.
Therefore, the behavior of the key to you, an engineer,
seems bizarrely counter-intuitive and even buggy.
But to an everyday person, it makes perfect sense.
Or at least that's the theory.
Let's look at it from the point of view of that everyday person.
Suppose you want to compute how much a $72 sweater will cost
after including 5% tax.¹
Pull out your handy pocket calculator² (or fire up Calc if you don't
have a pocket calculator) and type
72 + 5% =
The result is 75.6, or $75.60,
which is the correct answer, because 5% of 72 is 3.6.
Add that to 72 and you get 75.6.
Similarly, suppose that sweater was on sale at 20% off.
What is the sale price?
72 − 20% =
The result is 57.6 or $57.60.
This is the correct answer,
because 20% of 72 is 14.4.
Subtract that from 72 and you get 57.6.
You can chain these percentage operations, too.
For example, how much will you have to pay for that 20%-off sweater
after adding 5% tax?
72 − 20% + 5% =
The result is 60.48.
A mathematician or engineer would have calculated the same result via
the equivalent computation:
72 × 0.80 × 1.05 =
Okay, now that we see how the calculator product designer intended the
percent key to be used,
let's look at what the calculator engineer
it has to do in order to match the specification.
When the user enters A + B % =,
the result should be
A × (1 + B/100) or
A + (A × B/100) after you distribute the multiplication
over the addition.
Similarly, when the user enters A − B % =,
the result should be
A × (1 − B/100) or
A − (A × B/100).
Aha, the calculator engineer says,
we can achieve this result by defining the percent key as follows:
When the user enters a value, an operator, a second value,
and then the percent key,
the first two values are multiplied and the product divided by 100,
and that result replaces the second value in the ongoing computation.
Let's walk through that algorithm with our first example.
If you watch the display as you go through this exercise,
you will even see the number 3.6 appear in the display
once you press the % key.
The percentage is calculated and replaces the original value
in the ongoing computation.
This algorithm also works for the chained percentages.
This even works for multiplication and division, but there is
much less call for multiplying or dividing a number
by a percentage of itself.
500 × 5 % =
The result of this is 12,500 because you are multiplying 500
by 5% of 500 (which is 25).
The result of 500 × 25 is 12,500.
You aren't computing five percent of 500.
You're multiplying 500 by 5% of 500.
(It appears that the authors of
this Knowledge Base article didn't consult
with the calculator engineer before writing up their analysis.
The percent key is behaving as designed.
The problem is that the percent key is not designed for engineers.)
What if you want to compute 5% of 500?
Just pick a dummy operation and view the result when you press
the percent key.
500 + 5 %
When you hit the percent key, the answer appears: 25.
You could've used the minus key, multiplication key, or division key
instead of the addition key.
It doesn't matter since all you care about is the percentage,
not the combined operation.
Once you hit the % key, you get your answer,
and then you can hit Clear to start a new calculation.
¹In the United States, quoted prices typically do not include
²In my limited experiments, it appears that no two manufacturers of
pocket calculators handle the percent key in exactly the same way.
Casio appears to handle it in a manner closest to the engineering way.
TI is closer to the layman algorithm.
And when you get into cases like 1 ÷ 2 %,
calculators start wandering all over the map.
Should the answer be 50, since 1/2 is equal to 50%?
Or should it be 0.005 since that is the numeric value of 0.5%?
Should that answer appear immediately or should it wait for you to hit the
I don't know what the intuitive result should be either.
1 ÷ 2 %
There are advanced settings in Windows,
settings which normal users not only shouldn't be messing with,
but which they arguably shouldn't even know about,
because that would give them just enough knowledge to be dangerous.
And no matter where you put that advanced setting,
somebody will tell you that you are an idiot.
Here they are on an approximate scale.
If you dig through the comments on this blog, you can probably find
every single position represented somewhere.
If you implement level N, people will demand that you implement
It doesn't stop until you reach the last step,
which is aggressively user-hostile.
(And then there will also be people who complain that
you went too far.)
From a technical standpoint,
each of the above steps is about ten to a hundred times harder
than the previous one.
If you put it in a configuration file, you have to write code
to load a parser and extract the value.
If you want an Advanced button, now you have to write a dialog box
(which is already a lot of work),
consult with the usability and user assistance to come up with
the correct wording for the setting, write help text,
provide guidance to the translators,
and now since it is exposed in the user interface,
you need to write automated tests and add the setting to the
It's a huge amount of work to add a dialog box,
work that could be spent on something that benefits a much
larger set of customers in a more direct manner.
That's why most advanced settings hang out at level 1
or, in the case of configuring program installation, level 2.
If you're so much of a geek that you want to change these
it probably won't kill you to fire up a text editor and write
a little configuration file.
Joel's count of
"fifteen ways to shut down Windows"
is a bit disingenuous, since he's counting six hardware affordances:
"Four FN+key combinations... an on-off button... you can close the lid."
Okay, fine, Joel, we'll play it your way.
Your proposal to narrow
it down to one "Bye" button, still leaves seven ways to shut down Windows.
And then people will ask how to log off.
In the beginning, there was one control library,
the window manager itself,
which provided buttons, static controls, edit controls,
scroll bars, list boxes, and combo boxes.
These controls were under the purview of the window manager team.
In Windows 3.1
a second control library known as the shell common controls was added,
but the library really didn't come into it own until Windows 95,
where it consisted
of the list view, header, tree view, tooltip,
toolbar, status bar, track bar, tab, updown, progress, hotkey,
and animation controls.
These controls were originally custom controls
written by the shell team for use in Explorer,
but since they seemed to be generally useful,
time was budged to do the
extra work to make the controls more suitable for general use,
testing the controls in combinations and scenarios
that Explorer itself didn't use,
and putting together formal documentation.
The shell common controls library underwent many changes over
the years, whereas the core intrinsic controls in the window manager
changed much more conservatively.
With Windows XP, the visual design team wanted to give the
look of Windows a new life.
Changing the non-client area (such as the window frame) was comparatively
straightforward, since programs didn't have much
control over that part of the window anyway.
As a result, they get the Windows XP look "for free".
The client area is another story.
Programs are in control of their client area,
where they can place controls that come with Windows,
their own custom controls,
or controls obtained from a third party library.
Making major changes to the core controls or the common controls
would be a high-risk endeavor
since there are thousands upon thousands of Windows program that
not only use them,
but use them in all sorts of crazy ways.
The initial stab at resolving these two conflicting goals
(making major changes to these controls to increase visual appeal
while simultaneously not changing them to maintain compatibility)
was to create a new DLL that would contain the "fancy new version"
of the core controls as well as the shell common controls.
The old DLLs USER32 and COMCTL32 stayed
where they were, so that old programs continued to get the behavior
they were expecting,
and the new XP-style controls were placed in a DLL named
UX stands for user experience,
which was the hot new buzzword at the time.
To avoid name collision with the old style controls,
the new controls got new names beginning with Ux.
For example, the UXCTRL version of the button control
was called UxButton.
New features could be added to these new Ux controls with wild abandon
without heed for backward compatibility since they were brand new controls.
There was nothing they had to be compatible with.
Explorer was changed to use these new controls instead of the old stodgy
and everything worked great.
Or so it seemed.
We thought we had cleverly sidestepped the backward compatibility problem
by creating entirely new controls,
but doing that created a whole new category of compatibility bugs.
Even though it's completely undocumented and unsupported,
programs like to
grovel into the internal data structures of other programs
manipulate those programs' windows.
In Explorer's case, it turns out that a lot of programs like to
go spelunking around Explorer's window hierarchy and use functions
like FindWindow and
to find the object of their affections.
For example, a program might use EnumChildWindows to
enumerate all the child windows of an Explorer browser,
and then use GetClassName
and lstrcmpi(szClassName, TEXT("button"))
to look for a specific control.
In this example, the target was a button,
but it could have been a list view or a tool bar.
Since all the new XP-style controls were named
things like UxButton and UxListView,
these programs which looked for a button by comparing against
the string "button" stopped working.
Of course, there was no guarantee that Explorer would even use
buttons at all;
Explorer was completely within its rights to revamp its user interface.
But that's not much consolation to the customers who paid good money
for these programs,
especially since magazine columnists are the types of people most
likely to be running (or indeed even writing!)
strange off-the-wall programs that pull these
sorts of nasty stunts in the first place.
Okay, so it is now a compatibility requirement that all the new window
classes have the same names as their old counterparts.
This created an impasse, since these controls needed to be created
by dialog boxes, and therefore they had to be globally-registered
But you can't have two global window classes with the same name,
because that would create ambiguity over which one the caller was
More brainstorming ensued, and a Plan C emerged.
The common controls library would take advantage of
and use the application manifest to control which
DLL a given window class name would resolve to.
Thus was born a new DLL also called COMCTL32,
but with a new version number—version 6.
Old programs would get version 5.82 just like they did
in Windows 2000.
New programs would have to use a manifest to specify that they wanted
Once again, the solution came with a new problem.
Since the entire COMCTL32 library got split
into two versions,
this meant that there were two versions of the image list code.
Whole new scenarios emerged, such as
putting a version 5 image list in a
version 6 tree view, or vice versa.
(As the linked thread notes illustrates, not all of the problems with
cross-version scenarios were caught in the initial release and had
to wait for a service pack for the fix to become available.)
Commenter Matt asks
how you're supposed to handle failures in functions
like fclose or CloseHandle.
Obviously, you can't.
If a clean-up function fails, there's not much you can do because,
well, how do you clean up from a failed clean-up?
These clean-up functions fall into the category of
"Must not fail for reasons beyond the program's control."
If a program tries to close a file and it gets an error back,
what can it do?
Practically speaking, nothing.
The only way a clean-up function can fail is if the program
fundamentally screws up,
say by attempting to close something that was never open
or otherwise passing an invalid parameter.
It's not like a program can try to close the handle again
(or worse go into loop closing the handle repeatedly until it
Remember this when writing your own clean-up functions.
Assuming the parameters are valid, a clean-up function must succeed.
(I will now ruin my rhetorical flourish by yammering about the
fclose function because if I don't,
people will bring it up in the comments anyway.
The fclose function does extra work before closing,
and that extra work may indeed run into problems,
but the important thing is that
when fclose returns, the stream is well and truly closed.)
Addendum: Once again I wish to emphasize that while it may
be possible for functions like fclose to run into errors
while they are closing the stream,
the point is that
the result of the call to fclose is always a closed stream.
I think most of the comments are losing sight of the point of my article
and rat-holding on the various ways fclose can run into
That's not the same as failing.
It never fails; it always succeeds, but possibly with errors.
Commenter BryanK notes that
only already-technical people (re)install Windows;
commenter Stu estimates the percentage at 99%.
That may be true in the steady state,
but the hard part is getting to that steady state.
When a new version of Windows is released,
the steady state is disrupted.
At that point, most people installing Windows aren't technical.
They're your technology columnist who is installing Windows and
viewing it through the eyes of a non-technical user,
then writing a column about it.
They're your average consumer who wants to check out
this new operating system.
These are the crazy people who stayed up late to buy
the product at the stroke of midnight,
and they're going to kick off an upgrade install
once they get home.
These initial impressions are crucial,
and innundating the user with
geeky questions they can't answer is not going to generate good buzz.
The steady state is also disrupted every year at Christmas.
The technology columnists are not as big a part of the picture,
but the non-technical end users are still around,
and Christmas is a common trigger for upgrading one's system.
So even though non-technical people rarely install Windows,
the steady state is upset every year.
What's more, whenever a new release of Windows comes out
all¹ the people who are installing Windows are non-technical.
That's why it's important for the installation process
to be as friendly to non-technical users as possible.
¹The word "all" here is about as accurate as the word "only"
in the original comment.
In addition to all the named values you can create underneath
a registry key with the
there is also the so-called default value which
you obtain by passing NULL or a pointer to a null
string as the lpValue.
This default value is also the value set and retrieved when you
call RegSetValue and
What's the deal with this default value?
The original 16-bit registry didn't have named values.
All it had were keys,
and associated with each key was a single piece of data:
The functions that operated on this data were
which explains why those functions
(1) don't have a lpValue parameter
and (2) set and retrieve only string data.
Because back in the 16-bit world,
that's all you had.
In the conversion to Win32, the registry gained new
capabilities, such as storing data in formats beyond
and storing multiple pieces of data under a single key,
using a name to distinguish them.
What used to be called simply "the value of a registry key"
(for since there was only one, there was no need to give it a name)
now goes by the special name the default value:
It's the value whose name is null.
There's nothing particularly special about the default value
aside from its unusual name.
A named value need not exist, and if it exists,
the data type could be anything.
Similarly, the default value need not exist, and its type can be anything.
At this point, it's just a value with a strange name.
One of my colleagues has a degree in economics,
and sometimes it manifests itself in strange ways.
My colleague moved to a new apartment building and rented
a parking space in the building's garage.
After a month of noticing that there was
usually an empty parking space or two on the street,
my colleague made the economic calculation that
the risk of not
finding a parking space nearby was outweighed by the savings
of not paying for a monthly parking space.
After a few more months, my colleague started experimenting
alternate side of the street
and noticed that they tended not to be enforced early
in the morning.
Once again, after some mental calculations, the extra few
hours of sleep were deemed worth the additional cost of the
occasional parking ticket.
The saga continues.
My colleague then determined that the city doesn't really care
that much if you don't pay your parking ticket.
(I personally find this hard to believe,
but that's how my colleague described it,
so there you have it.)
The unpaid tickets piled up.
And then something happened to put an end to this little scheme:
The prospect of home ownership.
My friend planned to move out of the apartment building and buy
a house in a different part of the city.
While the city may not care about unpaid parking tickets,
banks definitely do,
and it was adversely affecting the interest rates on the home loan offers.
My colleague sat down and did the math and calculated that
the time-discounted savings over the life of the loan
outweighed the present cost of paying off all the parking tickets.
Off to the parking ticket payment office we go.
"Hi. I'd like to pay my parking tickets."
The person at the desk took down the pertinent information and
went to the computer to print out the tickets so they could be paid.
This was back in the days of
dot matrix printers
so the printer buzzed noisily and could be heard throughout the room.
The tickets printed.
People in the office started to take notice,
wandered over to the printer to see what was going on,
and then, once they realized what was happening,
began to clap and cheer.
Handing over the check to pay for the tickets earned
my colleague a standing ovation.
(By the way,
a parking holiday in Seattle.)
[Note: An incomplete version of this article was
mistakenly published a day early.
It has been updated to the finished version and
moved to its correct publication date.]
A bug report came in:
When I go to the Power Options control panel and select
Edit Plan Settings,
the Turn off display combo-box is disabled.
Is this a bug?
Shortly thereafter, this response was submitted:
Do you see a big yellow warning over the
Turn off display that says that some settings
are managed by your system administrator,
and a link called
Why can't I change some settings?
Yes, my machine is joined to a domain, and I see that yellow warning.
This is a fact of life.
People can't see what is right in front of their face.
Even though there's a warning right above the disabled item
explaining that it can't be changed due to an administrative setting,
even though there's a link on the page whose text directly
addresses the issue they are asking about,
even though they
confirm the existence of the explanatory text when asked,
they still don't read it or understand it.
It's another case of
You are so focused on the task of clicking on the combobox that
you completely disregard any other information because you simply
aren't expecting it to be there.
Depending on what version of Windows you're running,
there may be a variety of support DLLs for things that
aren't formal product components, but which are merely along for the ride.
For example, Windows 95
came with MFC30.DLL because the Fax Viewer was written with
the help of MFC 3.0.
But if you look at Windows 98, MFC30.DLL is gone.
What happened is that Windows 98 didn't have a fax viewer
that used MFC 3.0.
The fact that some MFC 3.0 DLLs wound up on the machine
with Windows 95 was merely a side effect of the implementation
and not a part of the product specification.
And in fact, if you chose not to install the Fax Viewer
during Windows 95 setup, you wouldn't have gotten
MFC30.DLL at all either,
because MFC30.DLL wouldn't have been needed.
We had a category of Windows 98 compatibility bugs from
programs that assumed that MFC30.DLL was a contractual part of Windows.
If the tester did a minimal install of Windows 95 and then
installed the application,
the application wouldn't run there either.
The application vendor simply assumed that MFC was part of Windows,
even though it wasn't.
In other words, the program didn't work even on Windows 95.
Is it a bug in Windows 98 if the program didn't work on Windows 95?
This problem persists today.
People go scrounging around the binaries that come with Windows
looking for something they can remora.
And then they're surprised when those binaries change or vanish entirely.
For example, one customer had reverse-engineered the Kodak image viewer in
Windows 2000 and wanted to keep using it in Windows XP.
those components are not included in Windows XP;
the Kodak image viewer was merely a stopgap solution until the
Windows XP fax and image viewer came along.
(The linked Knowledge Base article has more information on that
I mention this because that customer, a Fortune 500 company,
was trying to copy the files from Windows 2000
and install them onto a Windows XP machine
and actually came to us asking for help in what may very well have
been a violation of the Windows license agreement!
(And certainly a violation of Microsoft's agreement with Kodak.)
(I now predict that everybody will comment on the last two sentences
and completely ignore the point of this article.)
Even without a nitpicker's corner, I have to worry about nitpickers.
I just have to do it in a more subtle way.
Here are some examples of changes I've made to upcoming entries
in order to forestall nitpicking:
What's scary is that I've noticed that I begun pre-emptively
nitpicking my own entries while I'm writing them.
In the balance between writing something that reads more naturally
and something that is more resiliant to nitpicking,
I've unfortunately started preferring the latter.
Observant readers may have noticed that I've slowly introduced
a section called
"Pre-emptive snarky comment" wherein I try to anticipate
drive-by "Hey wouldn't it be hilarious if I
ridiculed Microsoft on a Microsoft employee's blog?" comments.
It seems to be largely successful,
although sometimes people will post the identical snarky comment
that I pre-empted.
These are probably the people who talk just to enjoy the sound of their
An extension of this is the "Now that you brought up something that sucks,
I'm going to tell you that it sucks" phenomenon.
This is pretty much guaranteed whenever I bring up anything that
is related to UAC and security,
since it appears that everybody agrees that UAC sucks,
so any blog entry that talks about elevation
invariably leads to comments about
There are also popular tangents, such as any article that mentions
installing software turning into a
"post your complaints about setup here" thread.
Some people are more indiscriminate and merely
bash Vista whenever they get a chance,
such as using a story about the psychology of how people fail to process
information that they see to
rant about how it's hard to copy text out of the event viewer.
(That article about how people fail to process information that they see
was indeed an unmitigated disaster.
Everybody got into arguing over how the message should have been presented
so the user would be more likely to see it,
but that completely misses the point.
The user positively confirmed, "I see the yellow warning."
The problem wasn't that the user didn't see the message;
the response confirmed that the user saw the message just fine.
What the user didn't do was process the information.
It's my fault for choosing a bad title.
Instead of "People can't see things that are right in front of them,"
I should have titled it "People see things but don't pay attention to them,"
opting for precision even though it meant I couldn't use the idiomatic
phrase can't see what's right in front of you.
What made it worse is that I fell for the trap.
I responded to the details instead of saying,
"Whether your suggestion would have helped the user see the message or not
is totally irrelevant to the point of the article.")
I also hadn't predicted that my discussion of
how reasonable people can disagree about how a setting should be exposed
would turn into a discussion of how to shut down your computer,
turning a footnote into the primary topic of discussion.
But that's a fairly common occurrence:
People focus on a side detail (which I added for color)
and ignore the point of the story.
Sometimes I think I'd be better off if I didn't give examples.
That way nobody could be distracted by them.