Skip to content

5. Portion exchanges

Grams become portions. This is the step that turns a macro target into something a client can actually follow, because nobody weighs 193 g of carbohydrate but everybody can count four slices of bread.

Reconcile against macro grams, never against kcal. The kcal column in the exchange table is a conventional rounded figure and reads about 3% low across a day; chasing it produces portion counts that miss the macros they were derived from.

The order matters

Groups are not filled in an arbitrary order, because several of them contribute to more than one macro. Filling protein before starch, for example, overshoots protein — starch carries 3 g of it per portion, and by the time seven portions of starch are in, that is another 21 g.

So: fix the groups that are set by rule, then fill the ones that absorb the remainder, in dependency order.

1. Fix the rule-driven groups

These are not derived from the macros. They come from the standing guidance.

Group Count Why
Vegetable 5–8, default 7 Half the plate at lunch and dinner is 3 portions each; one more elsewhere
Fruit 2 Two a day, tart preferred — see Exchange lists
Dairy 0–3, default 2 0 if avoided or not tolerated; 2 normally; 3 where calcium is a priority

Vegetables are a minimum the client may exceed, but the count used in the arithmetic is the one written down. Do not budget for 5 and plan for 8.

2. Subtract what they contribute

remaining_carb    = carb_target    − (veg + fruit + dairy carb)
remaining_protein = protein_target − (veg + dairy protein)
remaining_fat     = fat_target     − (dairy fat)

3. Starch — from the remaining carbohydrate

Starch is the only group left that carries meaningful carbohydrate, so it is fully determined:

starch = round(remaining_carb / 15)

Then subtract what starch contributes: 3 g protein and 1 g fat per portion.

4. Protein — from what is left of the protein

protein = round(remaining_protein / 7)

Then subtract 1 g of fat per portion.

5. Fat — from what is left of the fat

fat = round(remaining_fat / 5)

6. Reconcile

Add the six groups back up and compare to the targets from step 4.

Macro Tolerance
Protein ±5 g
Carbohydrate ±10 g
Fat ±5 g

Outside tolerance, adjust by one portion at a time, cheapest first:

  • Carbohydrate off → ±1 starch (moves carb 15, protein 3, fat 1)
  • Fat off → ±1 fat (moves fat 5 only — the cleanest lever there is)
  • Protein off → ±1 protein (moves protein 7, fat 1)
  • Still stuck → ±1 vegetable, staying within 5–8

Re-check after each single move. Two moves at once is how a reconciliation oscillates.

Worked example

Continuing: 133 g protein, 193 g carbohydrate, 55 g fat.

1  Fixed:  veg 7 · fruit 2 · dairy 2
           veg    → carb 35, protein 14
           fruit  → carb 30
           dairy  → carb 24, protein 16, fat 6

2  remaining_carb    = 193 − 35 − 30 − 24 = 104
   remaining_protein = 133 − 14 − 16      = 103
   remaining_fat     =  55 − 6            =  49

3  starch  = round(104 / 15) = 7      → carb 105, protein 21, fat 7
4  protein = round((103 − 21) / 7)
           = round(82 / 7)   = 12     → protein 84, fat 12
5  fat     = round((49 − 7 − 12) / 5)
           = round(30 / 5)   = 6      → fat 30

6  Totals
   carb    105 + 35 + 30 + 24     = 194   target 193   +1   ✓
   protein  21 + 84 + 14 + 16     = 135   target 133   +2   ✓
   fat       7 + 12 + 30 + 6      =  55   target  55    0   ✓

First pass, inside tolerance on all three. That is normal — the order of operations is what makes it normal.

### Daily portions
starch 7 · protein 12 · fat 6 · vegetable 7 · fruit 2 · dairy 2
Delivers: carb 194 g · protein 135 g · fat 55 g

Legumes are counted twice, and that is not a rounding error

Half a cup of cooked legumes is 1 starch portion and 1 protein portion. When step 7 fills a starch slot with lentils, it is also filling a protein slot, and both counters come down.

This is what makes a plant-forward menu arithmetically possible. It is also the easiest place to make a mistake in the other direction — counting the lentils twice against the same slot, or forgetting the second count entirely and leaving the client 20 g of protein short. Step 9 checks it.

When a group has to be dropped

A vegan client has no dairy portions. A client who cannot tolerate any of the listed starches at all is rarer but happens.

Do not adjust downstream. Come back to this step, set the group to zero, and re-run from part 2. The macro targets from step 4 do not change; what changes is which groups absorb them.

Dropped Absorbed by
Dairy +1 protein, +1 starch, +1 fat approximately
All animal protein Legumes — which raises starch, so recheck carbohydrate
Gluten-containing starch Nothing changes; the group survives, the food list shrinks
Fruit Vegetables and starch. Do not drop fruit for a preference — see step 8

If dropping a group cannot be absorbed inside tolerance, the constraint is tighter than the menu can express, and Notes for you says so plainly rather than the arithmetic quietly failing.


Previous: 4. Macro split · Next: 6. Meal schedule