A little float explorer program

April 23, 2025 C/C++ development and debugging. No comments , , ,

Karl’s 1st year C programming course included IEEE floating point representation.  It’s good to understand that representation, but pretty silly to try to do those conversions by hand.

I remember covering this in our computer organization course, but by that time I’d already figured it out for my own purposes.  I wasn’t smart enough to look it up, and figured it out the hard way by reverse engineering the layout with printfs or the debugger or something like that.

I couldn’t help myself and wrote a little program to unpack a (32-bit) float into it’s representative parts.  The idea is that we have a number in the form:

\begin{equation}\label{eqn:float32:1}
\pm 1.bbbbbbbb x 2^n
\end{equation}

The sizes of those components in a 32-bit C float type are:

  • 1 sign bit,
  • 8 exponent bits,
  • 1 implied 1 mantissa bit,
  • 23 mantissa bits,

where the exponent has a bias (127 = (1<<7)-1) so that the hardware doesn’t have to do any twos complement manipulation.

I’ve put my little floating point explorer program on github. Here is some sample output:

value:    0
hex:      00000000
bits:     00000000000000000000000000000000
sign:     0
exponent:  00000000                        (0+0)
mantissa:          00000000000000000000000
number:          0.00000000000000000000000 x 2^(0)

value:    inf
hex:      7F800000
bits:     01111111100000000000000000000000
sign:     0
exponent:  11111111
mantissa:          00000000000000000000000
number:   +inf

value:    -inf
hex:      FF800000
bits:     11111111100000000000000000000000
sign:     1
exponent:  11111111
mantissa:          00000000000000000000000
number:   -inf

value:    nan
hex:      7FC00000
bits:     01111111110000000000000000000000
sign:     0
exponent:  11111111
mantissa:          10000000000000000000000
number:   NaN

value:    1.1754944e-38
hex:      00800000
bits:     00000000100000000000000000000000
sign:     0
exponent:  00000001                        (127 -126)
mantissa:          00000000000000000000000
number:          1.00000000000000000000000 x 2^(-126)

value:    3.4028235e+38
hex:      7F7FFFFF
bits:     01111111011111111111111111111111
sign:     0
exponent:  11111110                        (127 +127)
mantissa:          11111111111111111111111
number:          1.11111111111111111111111 x 2^(127)
Smallest denormal:

value:    1e-45
hex:      00000001
bits:     00000000000000000000000000000001
sign:     0
exponent:  00000000                        (0-126)
mantissa:          00000000000000000000001
number:          0.00000000000000000000001 x 2^(-126)
Largest denormal:

value:    1.1754942e-38
hex:      007FFFFF
bits:     00000000011111111111111111111111
sign:     0
exponent:  00000000                        (0-126)
mantissa:          11111111111111111111111
number:          0.11111111111111111111111 x 2^(-126)

value:    1
hex:      3F800000
bits:     00111111100000000000000000000000
sign:     0
exponent:  01111111                        (127 +0)
mantissa:          00000000000000000000000
number:          1.00000000000000000000000 x 2^(0)

value:    -2
hex:      C0000000
bits:     11000000000000000000000000000000
sign:     1
exponent:  10000000                        (127 +1)
mantissa:          00000000000000000000000
number:         -1.00000000000000000000000 x 2^(1)

value:    6
hex:      40C00000
bits:     01000000110000000000000000000000
sign:     0
exponent:  10000001                        (127 +2)
mantissa:          10000000000000000000000
number:          1.10000000000000000000000 x 2^(2)

value:    1.5
hex:      3FC00000
bits:     00111111110000000000000000000000
sign:     0
exponent:  01111111                        (127 +0)
mantissa:          10000000000000000000000
number:          1.10000000000000000000000 x 2^(0)

value:    0.125
hex:      3E000000
bits:     00111110000000000000000000000000
sign:     0
exponent:  01111100                        (127 -3)
mantissa:          00000000000000000000000
number:          1.00000000000000000000000 x 2^(-3)

Shoutout to Grok for the code review and the code fragments required to show the representation of NaN, \( \pm \infty \), and denormalized numbers. Grok offered to help extend this to double and long double representations, but where is the fun in letting it do that — that’s an exercise for another day.

more git-fu: reset –hard after force push

April 10, 2025 Linux No comments , , ,

When I have a branch that I’m sharing only between myself, it’s occasionally helpful to force push and then reset all the other repo versions of the branch to the new one.  Yes, I know that’s inherently dangerous, and I’ve screwed up doing this a couple times.

Here’s one way to do it:

# alias gitbranch='git branch --show-current'
git fetch
git reset origin/`gitbranch` --hard

When I do this, I always first check that the branch on the repo in question is pushed to the upstream branch (i.e., I can consider the current state discardable), and sometimes I’ll also do a sanity check diff against the commit hash that came with the fetch to see what I’m going to get with the reset.

Assuming that I still want to be stupid and dangerous, is there an easier way to do it?

I asked Grok if there was an short cut for this action, and as expected, there’s a nice one:

git fetch
git reset @{u} --hard

Here the @{u} is a shorthand for the current upstream branch.

Grok suggested a one liner using && for the two commands, but when I’m being dangerous and (possibly) stupid I’d rather be more deliberate and do these separately, so that I can think between the two steps.

git diff against previous

March 30, 2025 Linux , , , ,

I’ve been using a simple home grown script (gitdiffc) to generate git diffs against the previous version for all files in a given commit.  It would run something like:

# git diff \
$(git log --pretty=format:%h -2 --reverse d86cc4b38db | tr "\n" " ")

The git log part, just gives two commit IDs. Example:

# git log --pretty=format:%h -2 --reverse d86cc4b38db
38aeb009b21
d86cc4b38db

I have a few files that I have to manually merge, as there are two many cherry-pick conflicts, so I was collecting information for that merge.  That included extracting the version that I would have wanted to cherry-pick, since :

git show d86cc4b38db:foo.cc > foo.cc.show

I also wanted a diff, of just that file, in the branch I am trying to pick from, but wasn’t sure how to get that easily without looking up the log, like I did in my ‘gitdiffc’ script that ran the log and diff command above.

I figured there had to be an easier way. Shout out to Grok, which pointed out that I can just use:

git diff d86cc4b38db^ d86cc4b38db -- foo.cc

This also means that I can simplify my ‘gitdiffc’ script so that it just runs:

# git diff d86cc4b38db^..d86cc4b38db

eliminating the nested git log command. That is simple enough that I don’t even need a script to remember how to do it. This should have been obvious, since I’ve used HEAD^ just like that so many times (i.e.: git reset HEAD^, to break up the last commit.)

Weighted geometric series

March 23, 2025 math and physics play , , ,

[Click here for a PDF version of this post]

Karl needed to evaluate the sum:

\begin{equation}\label{eqn:weightedGeometric:20}
S = \sum_{k = 0}^9 \frac{a + b k}{\lr{ 1 + i }^k}
\end{equation}

He ended up using a spreadsheet, which was a quick and effective way to deal with the problem. I was curious about this sum, since he asked me how to sum it symbolically, and I didn’t know.

Mathematica doesn’t have any problem with it, as seen in fig. 1.

fig. 1. A funky sum.

How can we figure this out?

Let’s write \( r = 1/(1+i) \) to start with, and break up the sum into constituent parts
\begin{equation}\label{eqn:weightedGeometric:40}
\begin{aligned}
S_n
&= \sum_{k = 0}^n \frac{a + b k}{\lr{ 1 + i }^k} \\
&= a \sum_{k = 0}^n r^k + b \sum_{k = 0}^n k r^k.
\end{aligned}
\end{equation}
We can evaluate the geometric part of this easily using the usual trick. Let
\begin{equation}\label{eqn:weightedGeometric:60}
T_n = \sum_{k = 0}^n r^k,
\end{equation}
then
\begin{equation}\label{eqn:weightedGeometric:80}
r T_n – T_n = r^{n+1} – 1,
\end{equation}
so
\begin{equation}\label{eqn:weightedGeometric:100}
T_n = \frac{r^{n+1} – 1}{r – 1}.
\end{equation}
Now we just have to figure out how to sum
\begin{equation}\label{eqn:weightedGeometric:120}
G_n = \sum_{k = 0}^n k r^k = \sum_{k = 1}^n k r^k.
\end{equation}
This looks suspiciously like the derivative of a geometric series. Let’s evaluate such a derivative, as a function of r:
\begin{equation}\label{eqn:weightedGeometric:140}
\begin{aligned}
\frac{d T_n(r)}{dr}
&= \sum_{k = 0}^n \frac{d}{dr} r^k \\
&= \sum_{k = 0}^n k r^{k-1} \\
&= \sum_{k = 1}^n k r^{k-1} \\
&= \inv{r} \sum_{k = 1}^n k r^k.
\end{aligned}
\end{equation}
Having summed the geometric series, we may also take the derivative of that summed result
\begin{equation}\label{eqn:weightedGeometric:160}
\begin{aligned}
\frac{d T_n(r)}{dr}
&= \frac{d}{dr} \lr{ \frac{r^{n+1} – 1}{r – 1} } \\
&= \frac{(n+1)r^n}{r – 1} – \frac{r^{n+1} – 1}{\lr{r -1}^2} \\
&= \frac{(n+1)r^n(r-1) – \lr{r^{n+1} – 1}}{\lr{r -1}^2}.
\end{aligned}
\end{equation}
Putting the pieces together, we have
\begin{equation}\label{eqn:weightedGeometric:180}
T_n = \frac{r}{\lr{r -1}^2} \lr{ (n+1)r^n(r-1) – \lr{r^{n+1} – 1} }.
\end{equation}

This means that our sum is
\begin{equation}\label{eqn:weightedGeometric:200}
S_n = a \frac{r^{n+1} – 1}{r – 1} + b \frac{r}{\lr{r -1}^2} \lr{ (n+1)r^n(r-1) – \lr{r^{n+1} – 1} }.
\end{equation}
Putting back \( r = 1/(1+i) \), and subsequent simplification, gives the Mathematica result. It’s not pretty, but at least we can do it if we want to.

Shout out to Grok that pointed out the derivative trick for the second series.  I’d forgotten that one.

Wonderful Life=Giving Radium

March 22, 2025 Incoherent ramblings

From “The Wide World” Magazine, June 1905 edition

“This remarkable substance is absolute and quick death to the germs of cancer, tumor, consumption, malaria, blood poison, ulcers and all forms of existing disease.  When it enters the system every vestige of disease is driven out, as no germ can live in its presence.”

The amusing thing is that the idea of this advertisement has a close analogue in modern medicine, as chemotherapy is essentially the same idea.  Chemotherapy is also a gross system wide attack on the body, a desperate hope that it can be used to kill off the cancer cells faster than the rest of the cellular structure of the body.  It’s the kind of treatment that future Bones, in Star Trek IV, will eventually be describing as “What is this, the dark ages?”

I have three of these “Wide World” magazines that I got in a “unknown” box of pulp fiction magazines from a second hand store when I was a kid (Argosy, Blue Boy, …).  The ads from these magazines are the best part.  I think I’ve posted a few more of them on my old blog, but I should systematically go through them for archival purposes, and share them all.