Fix PLC BCD conversion losing digits in division

6 min read · Published November 7, 2026

Converting a 32-bit binary operand to BCD keeps 8 decimal digits and tops out at 99,999,999, so 123000000 returns as 23000000 and the divide runs on an operand that lost its ninth digit. Keep large operands in binary, or scale both by an exact power of two and verify the quotient at the range limits.

Your divide instruction is rarely the fault. The loss happens one rung earlier, when a 32-bit binary operand is converted to BCD. BCD stores one decimal digit in 4 bits, so a double-word conversion holds 8 decimal digits and tops out at 99,999,999 counts. Convert 123,000,000 counts that way and the stored value is 23,000,000: the ninth digit is gone before the divide runs, and no division instruction can put it back. The quotient then reads low by exactly what the conversion dropped, and it looks normal enough to pass a glance. Keep large operands in binary and divide in binary, or scale both operands by an exact power of two so each stays inside 8 digits. This article shows why the digits vanish, what the wrong quotient looks like, and both fixes.

Why the quotient is wrong before the divide runs

BCD packs one decimal digit into 4 bits. A 16-bit word holds 4 digits, a 32-bit double word holds 8 digits, and the largest value an 8-digit conversion can store is 99,999,999. A binary double word holds 2,147,483,647 signed, which needs 10 digits. Every input above 99,999,999 counts has a ninth digit, and the conversion stores only the low 8: a 9-digit input loses everything from the 100,000,000 place up.

The common workaround builds exactly this trap. The divisor is loaded with LDD V2100, converted with BCD, stored with OUTD V2102, and the divide runs as DIVD V2102. Convert the dividend the same way and its top digit drops at the conversion, before DIVD executes. The divide itself runs normally and writes a normal-looking result, which is why the error survives a first check.

Symptoms and what each points to

  • The quotient is correct on small counts and goes wrong as counts climb. An operand crossed 99,999,999 counts and lost its ninth digit in the conversion.
  • The display value looks like the true value with its leading digit missing. 123,000,000 counts stored as 23,000,000 is the conversion wrapping at 100,000,000.
  • The result is low by a large, steady amount at high counts. The truncated operand feeds the divide on every scan.
  • Small off-by-a-few errors appear after you scaled both operands. A right shift dropped different fractional bits from each one.
  • A register or display shows a magnitude far from the raw value. One side reads BCD as binary or the reverse, the problem in HMI panel shows nonsense numbers from a PLC BCD analog register.

Example: 123,000,000 counts divided by 10,000 counts per unit

Inputs. Dividend: 123,000,000 counts, held as a binary double word in V2000 to V2001. It has 9 digits. Divisor: 10,000 counts per unit, a binary double word in V2100 to V2101.

Rule. An 8-digit BCD conversion stores each decimal digit in 4 bits and keeps the low 8 digits, so it returns the input modulo 100,000,000.

Arithmetic.

  1. Conversion: 123,000,000 − 1 × 100,000,000 = 23,000,000, so 23,000,000 is stored as BCD.
  2. Quotient in the BCD path: 23,000,000 ÷ 10,000 = 2,300.
  3. True quotient: 123,000,000 ÷ 10,000 = 12,300.
  4. Error: 12,300 − 2,300 = 10,000 units low, and 10,000 ÷ 12,300 = 0.81, so the reading is 81 percent low.

Result. The display reads 2,300 units where the process ran 12,300 units.

Decision. The dividend needs 9 digits and the conversion stores 8, so the BCD path is disqualified for this job no matter what the divisor is. Divide in binary, or scale exactly as the next section shows.

Keep the divide in binary

Conversion is the only step that loses digits, so take it out. Look in the instruction reference for a divide that accepts two binary double words directly. Load both operands as binary and leave every BCD conversion out of the rung.

If the divide available to you runs on BCD operands and both operands will stay at or below 99,999,999 counts, the conversion is safe for those values. Hold the operands inside that range at the source: clamp operator entries and presets, the pattern in clamp HMI numeric entry limits in PLC ladder logic. If the operand comes from a counter that resets, save the previous count before a PLC counter reset so the total you divide stays complete.

Scale both operands only when the shift is exact

Dividing dividend and divisor by the same factor leaves the quotient unchanged in exact arithmetic. Integer math truncates, and truncation breaks that identity unless the factor divides both operands exactly.

A right shift by n bits divides a positive binary value by 2^n and discards the low bits. Shift both operands right by 7 bits, a factor of 128, and 123,000,000 becomes 960,937 (from 960,937.5) while 10,000 becomes 78 (from 78.125); 960,937 ÷ 78 gives 12,319 against a true quotient of 12,300. The dropped fractional bits changed the ratio by 19 counts.

A factor of 16 is exact for this pair: 123,000,000 ÷ 16 = 7,687,500 and 10,000 ÷ 16 = 625, so shift both operands right by 4 bits and 7,687,500 ÷ 625 = 12,300, the true quotient. It also fits the 8-digit ceiling. Use a shift only when 2^n divides both operands exactly, or when the worst-case truncation error at the range limits sits inside your process tolerance.

Nibble shifts and rounding on BCD values

On values you know are BCD, a nibble shift moves whole decimal digits and runs faster than a divide. SHFR K4 shifts one decimal digit right and divides by 10, SHFR K8 divides by 100, SHFL K4 multiplies by 10, and SHFL K8 multiplies by 100. The same 4-bit right shift on a binary operand divides by 16, so confirm the data format before you reuse these.

For a BCD value with 1 implied decimal place, the rounding rung adds one half, then shifts:

LD V2000    // BCD value with 1 implied decimal place
ADD K5      // add one half
SHFR K4     // divide by 10 in BCD
OUT V2001

Stored 16 means 1.6: 16 + 5 = 21, and shifting one decimal digit right gives 2. Stored 14 means 1.4: 14 + 5 = 19, and the shift gives 1. The rung rounds half up, and it belongs to BCD math only.

Checks before the rung goes back in service

Force outputs off or keep the machine in a safe state while you test.

  1. Write the largest real operand into the registers, step the rung once in a single scan, and read the stored double word back before and after every conversion or shift.
  2. Compare the quotient with a hand calculation at a mid-range value, the largest expected value, and a value not divisible by the scaling factor.
  3. Confirm the stored values still match the original digit for digit after conversion. A 9-digit input never will, which is the signal to keep binary in place.
  4. Watch the first production cycles over 10 to 15 minutes: a quotient that goes suddenly wrong as counts climb past 99,999,999 means a conversion is still in the path.

Recommendation

Recommendation: Divide in binary. Use the divide in your instruction reference that takes two binary double words and keep every BCD conversion out of the rung. If your divide runs on BCD operands, scale both operands by a power of two that divides each exactly, shift right n bits for a factor of 2^n, hold each operand at or below 99,999,999 counts, and test the largest real operand before you enable the rung. Reserve SHFR and SHFL nibble shifts for values you know are BCD.

Questions

How large can a 16-bit BCD value be?

Four bits hold one decimal digit, so a 16-bit word carries 4 digits and stops at 9999. The 32-bit double word in this article carries 8 digits and stops at 99,999,999. A 16-bit conversion fails the same way one digit earlier: 10000 wraps to 0000, and every value above 9999 loses its fifth digit.

What is the largest value the binary path can hold?

A signed 32-bit binary double word holds up to 2,147,483,647 and an unsigned one holds 4,294,967,295. Both pass the 8-digit BCD ceiling of 99,999,999, which is why the conversion is the step to remove. Divide in binary and convert only the final quotient to BCD for display, since a scaled quotient almost always fits in 8 digits.

Why does adding 5 before the BCD shift round correctly?

The stored value 16 means 1.6 with one implied decimal place. Adding 5 moves the halfway point across the digit boundary: 16 + 5 = 21, and shifting one decimal digit right truncates to 2. A stored 14, meaning 1.4, becomes 19 and truncates to 1. Any decimal part of 5 or higher rounds up, so the rung rounds half up.

Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.

Keep reading

Build your signAsk for a quote