You are not alone, I am lost somewhere between Wolfram Language, math and physics 97% of the time. I used ConstantArray as a easy way to generate repeated frequency values the length of the mass span. ConstantArray[x,4] -> {x,x,x,x} so I just repeated the frequencies for the length of the mass span. That way, all data is weighted properly. I would not recommend trying this with large data sets but for lists of under several hundred elements it is a straightforward method.
Note that I erred in the data table so the proper result is 39. Technically, you can not get more significant digits than the least of your data, so you can only resolve to 39. Here is a corrected code block...
Block[{x = {{{20, 24}, 20}, {{25, 29}, 24}, {{30, 39}, 45}, {{40, 54},
30}, {{55, 59}, 5}, {{60, 69}, 4}}, m, f, a},
m = Table[Range[x[[i, 1, 1]], x[[i, 1, 2]]], {i, 1, Length@x}];
f = Table[ConstantArray[x[[i, 2]], Length[m[[i]]]], {i, 1, Length@x}];
a = Flatten[m].Flatten[f]/Total[Flatten[f]];
Column[{
StringForm["Given a mass-frequency table: ``",
MatrixForm[x\[Transpose]]],
StringForm["The table range of masses m \[Rule] ``",
m // MatrixForm],
StringForm["Corresponding frequencies f \[Rule] ``",
f // MatrixForm],
StringForm[
"Thus m*f/(Total@f) evaluates average a \[TildeTilde] ``",
Round[N@a, 1]]
}]
]