[This is a page from Jonathan Dushoff’s math wiki, adapted for use as a test of my Working Markup blog-post system. Scroll down for info about how this post is made, including source code. -lw]

On this page, I use the free software environment R to construct a nomogram that I read about in a recreational math book when I was a kid. This nomogram solves quadratic equations.


You can print out the nomogram, and use a ruler to read off the solutions to the quadratic equation, where the line from ±b to c intersects the scale.


The example above shows the solutions to the equation x2-3x-5=0. The dashed line connecting b to c shows the positive solution (4.2), and the dotted line connecting -b to c shows the negative solution (-1.2).


In this example (x2-5x+1=0), both solutions are positive (0.2 and 4.8), thus only the dashed line intersects the scale.


We want to draw lines from (0,b) to (1,c) that will pass through a point labeled with r, where r is a root, satisfying r2+br+c=0. The equation for our line is y=b+(c-b)x. Solve the quadratic to obtain c=-r2-br, and substitute into the line equation to get y=b-(r2+br+b)x.

If we want all lines corresponding to r to go through our point, we must find one independent of b. We do this by setting x=1/(r+1), to yield y=-r2/(r+1).


Define and call a nomogram function.

pdf(height=9.5, width=6.5)
nomogram <- function(xoff=0.1, asp=1/16){
	plot(NULL, NULL, asp=asp,
		main = expression(x**2 %+-% bx + c == 0),
		xlim=c(-xoff, 1+xoff), ylim=c(-10,10), axes=FALSE,
		xaxs="i", yaxs="i",
		xlab="", ylab=""

	vertical_axis <- function(pos, side=2){
		axis(side, pos=pos, at=-10:10)
		axis(side, pos=pos, at= seq(-10, 10, by=0.5), 
			labels=FALSE, tcl=-0.4)
		axis(side, pos=pos, at= seq(-10, 10, by=0.1), 
			labels=FALSE, tcl=-0.2)

	vertical_axis(1, 4)
	text(0.05, 9, "b")
	text(0.95, 9, "c")

	r = seq(0, 10, length.out=1001)
	lines(1/(r+1), -r^2/(r+1))

	rticks <- function(r, tcl, asp=1, labels=FALSE, ll=0.9){
		x <- 1/(r+1)
		y <- -r^2/(r+1)
		yx <- (r^2+2*r)*asp
		rad <- sqrt(1+yx^2)
		xp <- 1/(asp*rad)
		yp <- yx/rad
		x0 <- x+yp*tcl/2
		x1 <- x-yp*tcl/2
		y0 <- y-xp*tcl/2
		y1 <- y+xp*tcl/2
		arrows(x0, y0, x1, y1, length=0)
			text(x-ll*yp*tcl, y+ll*xp*tcl, r)

	rticks(seq(1, 10, by=1), 0.08, asp, labels=TRUE)
	rticks(seq(0, 10, by=0.5), 0.05, asp)
	rticks(seq(0, 4, by=0.1), 0.03, asp)
	rticks(seq(4, 10, by=0.25), 0.04, asp)


Use make to make the example code below depend on the R environment from above (using our custom R rules).

Make a nomogram, then define and make example lines.

eqLines <- function(a, b){
	abline(a, b-a, lty=2, lwd=1.5)
	abline(-a, b+a, lty=3, lwd=1.5)
eqLines(-3, -5)

Here’s another example.

eqLines(-5, 1)


# setpdf(height=9.5, width=6.5) # This is a theobio/Rprep magic command

Export source code

This project is designed for reproducible research.

  • This entire website (including the source text of this blog post, with all the source code included) is available for cloning at I’m planning to write instructions for processing it soon.
  • To reproduce the full blog post you’ll need to have the following installed: Jekyll, git, R, latexml, GNU make, perl (and maybe other things - bug reports welcome).
  • Here is an automatically-generated tar file of the source file contents: wmd_export.tgz. You should be able to unpack this directory and simply run ‘make example.Rout.png’ to build the first image above, and similar commands to build the other output files.
  • To reproduce these outputs you will need GNU make, perl, and R installed.

To see the source text of this blog post, with the R and makefile code embedded, see

See also a discussion of how this is put together at and