Steel pipe weight tables look like data: 52 nominal sizes from 1/8" to 108", up to 17 schedules each,
405 rows with outside diameter, wall thickness and weight per foot and per metre (ASME B36.10M / B36.19M
values, as tabulated in Wikipedia's "Nominal Pipe Size" article). I keep them as JSON
for a weight calculator, and I wanted a test that every row is right, not just "close enough".
A pipe is a ring, so the weight should follow from two numbers. The question was whether all of the
table follows from them, to the last printed digit. It does, but only once you use the same constants,
and the same starting dimensions, as the people who made the table.
The formula
The cross-section of a pipe with outside diameter D and wall t is
A = π/4 × (D² − (D − 2t)²) = π × (D − t) × t Weight per length is area × density. Carbon steel is 0.2836 lb/in³ (that is 7850 kg/m³, the same
steel), and a foot is 12 in, so
lb/ft = 0.2836 × 12 × π × (D − t) × t = 10.6915 × (D − t) × t (D, t in inches) kg/m = 7850 × π × 10⁻⁶ × (D − t) × t = 0.0246615 × (D − t) × t (D, t in mm) Test 1: does the table follow the textbook constant?
The weights are printed to two decimals, so "exact" means: compute, round to 0.01, compare.
import json, math pipes = json.load(open("pipe.json"))["pipes"] rows = [(p, s) for p in pipes for s in p["schedules"]] def matches(k): return sum( s["lb_ft"] == round(k * (p["od_in"] - s["t_in"]) * s["t_in"], 2) for p, s in rows ) print(matches(0.2836 * 12 * math.pi)) # 202 of 405 print(matches(10.69)) # 405 of 405 With the physically "correct" constant 10.6915, only 202 of 405 rows match. With the rounded
10.69, all 405 do. The difference is 0.014 %, invisible in practice, but it moves the
second decimal on half the larger sizes (e.g. 24" Sch 140: 483.57 with 10.69, 483.64 with 10.6915).
That is not a coincidence or an error in the table: ASME B36.10M itself gives the plain-end weight as
10.69 × (D − t) × t. The table is generated from that formula, not measured. If your calculator uses
10.6915 (or 0.2836 lb/in³ from a materials page), you will "disagree" with the standard on 203 rows.
Use the standard's constant when you reproduce the standard's table.
Test 2: the metric column
The table also prints D and t in millimetres, so the obvious check is the metric formula on the metric
dimensions:
def matches_mm(k, from_inches): n = 0 for p, s in rows: D = p["od_in"] * 25.4 if from_inches else p["od_mm"] t = s["t_in"] * 25.4 if from_inches else s["t_mm"] n += s["kg_m"] == round(k * (D - t) * t, 2) return n print(matches_mm(0.0246615, from_inches=False)) # 201 of 405 print(matches_mm(0.0246615, from_inches=True)) # 404 of 405 print(matches_mm(0.02466, from_inches=True)) # 235 of 405 On the printed millimetres only 201 rows match. The reason is that the printed mm values are
rounded: a 3/8" wall is 9.525 mm, printed as 9.52; 12.75" OD is 323.85 mm, printed as 323.8.
The kg/m column was computed from the exact inch dimensions converted to mm, not from the mm
numbers printed next to it. Do that and 404 rows match.
The 405th (24" Sch 140) computes to 719.734987… and the table says 719.74. That is a floating-point
tie: with the full constant 7850 × π × 10⁻⁶ = 0.02466150233 it is 719.73506, which rounds up. So all
405 rows are reproducible. The commonly quoted short constant 0.02466 only gets 235.
Two lessons in one column:
- Metric pipe dimensions are conversions, not a separate design. NPS pipe is an inch standard. Store the inch values as the source of truth and derive millimetres for display.
- Never compute from a rounded display value when the unrounded one exists. Here the error is at most 0.14 % (on rows over 5 kg/m), small but enough to fail an exact test and to make two calculators disagree.
Test 3: don't convert one weight column into the other
A tempting shortcut is to store lb/ft only and show kg/m = lb/ft × 1.488164. For big pipes that is
fine. For small ones it is not, because lb/ft is already rounded to 0.01:
| Size | lb/ft (table) | × 1.488164 | kg/m (table) | Error |
|---|---|---|---|---|
| 1/8" Sch 30 | 0.21 | 0.313 | 0.32 | 2.3 % |
| 1/8" Sch 80 | 0.31 | 0.461 | 0.47 | 1.8 % |
| 1/4" Sch 40 | 0.43 | 0.640 | 0.63 | 1.6 % |
The rounding step of 0.01 lb/ft is 4 % of a 1/4 lb weight. Both columns have to be computed from the
geometry, each in its own unit, and rounded once at the end.
What this means for a calculator
If you build one from this table: keep OD and wall in inches as the stored values, compute lb/ft with
10.69 and kg/m with 7850 × π × 10⁻⁶ from the converted dimensions, and add a test that walks all 405
rows and requires an exact match at two decimals. When an imported row then fails, it is a
transcription error, not a "rounding thing", and the test tells you which row.
The same pattern works for any table generated from a formula (rebar, where lb/ft = 2.67 × d² holds
within 0.2 % for #3 to #18, flat bar, sheet gauges): find the generating formula, find their
constant, find their source unit, and the whole table becomes a one-line test.
The full table, with a per-size calculator for plain-end weight and the formula worked through for
each NPS, is on the steel pipe schedule chart.

