Find Closest Resistor Value

This is a simple program that does a simple but often needed thing - prints the closest 1% (E96) or 5% (E24) resistor value from an entered desired value...


Although it's easy enough to consult a resistor value table from the web, this is easier, especially handy when using trimpots to dial in a circuit. For more information check out the Wikipedia page for the E series of preferred numbers.

Download the fcrval.zip file for compiled binaries for Linux and Windows plus the QBasic source code and docs.

Here's the QBasic source code...


REM a program for finding standard resistor values
REM by WTN, last mods 20180117 20210412 20250514
PRINT "===== Find Closest Resistor Value ====="
PRINT "Finds the closest stock 1% and 5% resistor values."
PRINT "Entry can include K or M suffix, output is standard"
PRINT "resistor notation. Enter an empty value to exit."
DIM valueE96(97), valueE24(25)
REM E96 values, extra decade value at the end to simplify code
DATA 100,102,105,107,110,113,115,118,121,124,127,130,133,137
DATA 140,143,147,150,154,158,162,165,169,174,178,182,187,191
DATA 196,200,205,210,215,221,226,232,237,243,249,255,261,267
DATA 274,280,287,294,301,309,316,324,332,340,348,357,365,374
DATA 383,392,402,412,422,432,442,453,464,475,487,499,511,523
DATA 536,549,562,576,590,604,619,634,649,665,681,698,715,732
DATA 750,768,787,806,825,845,866,887,909,931,953,976,1000
FOR i = 1 TO 97: READ valueE96(i): NEXT i
REM E24 values+decade
DATA 10,11,12,13,15,16,18,20,22,24,27,30
DATA 33,36,39,43,47,51,56,62,68,75,82,91,100
FOR i = 1 TO 25: READ valueE24(i): NEXT i
entervalue:
LINE INPUT "Desired value: ", desired$
desired$ = LTRIM$(RTRIM$(UCASE$(desired$)))
IF desired$ = "" THEN GOTO exitprogram
IF LEFT$(desired$, 1) = CHR$(0) THEN GOTO exitprogram
mult = 1: num$ = desired$
IF RIGHT$(desired$, 1) = "K" THEN mult = 1000: num$ = LEFT$(num$, LEN(num$) - 1)
IF RIGHT$(desired$, 1) = "M" THEN mult = 1000000: num$ = LEFT$(num$, LEN(num$) - 1)
REM num$ must contain only 0-9 and no more than one decimal point
E = 0: E1 = 0: PC = 0
FOR i = 1 TO LEN(num$)
 a$ = MID$(num$, i, 1)
 IF ASC(a$) < ASC("0") OR ASC(a$) > ASC("9") THEN E1 = 1
 IF a$ = "." THEN E1 = 0: PC = PC + 1
 IF E1 = 1 THEN E = 1
NEXT i
IF E = 0 AND PC < 2 THEN GOTO entryok
PRINT "Don't understand that, try again"
GOTO entervalue
entryok:
REM calculate desired value from string and multiplier
desiredR = VAL(num$) * mult
IF desiredR >= .1 AND desiredR <= 100000000 THEN GOTO valueok
PRINT "Value must be from 0.1 to 100M"
GOTO entervalue
valueok:
REM determine multiplier to convert stored values
norm = .001
IF desiredR >= 1 THEN norm = .01
IF desiredR >= 10 THEN norm = .1
IF desiredR >= 100 THEN norm = 1
IF desiredR >= 1000 THEN norm = 10
IF desiredR >= 10000 THEN norm = 100
IF desiredR >= 100000 THEN norm = 1000
IF desiredR >= 1000000 THEN norm = 10000
IF desiredR >= 10000000 THEN norm = 100000
REM determine lower value match, upper match is one more
REM compare to a slightly smaller value to avoid FP errors
FOR i = 1 TO 96
 IF desiredR > valueE96(i) * norm - .00001 THEN v1 = i: v2 = i + 1
NEXT i
lowerE96 = valueE96(v1) * norm
upperE96 = valueE96(v2) * norm
REM do the same for E24 series, using norm*10 since E24 values are 2 digit
FOR i = 1 TO 24
 IF desiredR > valueE24(i) * norm * 10 - .00001 THEN v1 = i: v2 = i + 1
NEXT i
lowerE24 = valueE24(v1) * norm * 10
upperE24 = valueE24(v2) * norm * 10
REM calculate error percentages for lower and upper values
lowerE96error = (1 - lowerE96 / desiredR) * 100
upperE96error = -(1 - upperE96 / desiredR) * 100
lowerE24error = (1 - lowerE24 / desiredR) * 100
upperE24error = -(1 - upperE24 / desiredR) * 100
REM determine which value has less error
REM in the event of a tie go with the higher value (user can pick)
closestE96 = lowerE96: IF lowerE96error >= upperE96error THEN closestE96 = upperE96
closestE24 = lowerE24: IF lowerE24error >= upperE24error THEN closestE24 = upperE24
REM print the closest value and error percentages for lower/upper values
PRINT "Closest E96 value = ";
R = closestE96: GOSUB convertE96: PRINT R$; SPACE$(7 - LEN(R$)); "(";
REM to detect exact matches compare to a range to avoid float errors
M = 0: IF closestE96 > desiredR - .0001 AND closestE96 < desiredR + .0001 THEN M = 1
IF M = 1 THEN PRINT "exact match)": GOTO printE24values
E$ = LEFT$(LTRIM$(STR$(lowerE96error + .0001)), 4)
R = lowerE96: GOSUB convertE96: PRINT "-"; E$; "%="; R$; ",";
E$ = LEFT$(LTRIM$(STR$(upperE96error + .0001)), 4)
R = upperE96: GOSUB convertE96: PRINT "+"; E$; "%="; R$; ")"
printE24values:
PRINT "Closest E24 value = ";
R = closestE24: GOSUB convertE24: PRINT R$; SPACE$(7 - LEN(R$)); "(";
M = 0: IF closestE24 > desiredR - .0001 AND closestE24 < desiredR + .0001 THEN M = 1
IF M = 1 THEN PRINT "exact match)": GOTO doneprintingvalues
E$ = LEFT$(LTRIM$(STR$(lowerE24error + .0001)), 4)
R = lowerE24: GOSUB convertE24: PRINT "-"; E$; "%="; R$; ",";
E$ = LEFT$(LTRIM$(STR$(upperE24error + .0001)), 4)
R = upperE24: GOSUB convertE24: PRINT "+"; E$; "%="; R$; ")"
doneprintingvalues:
GOTO entervalue: REM loop back to enter another value
exitprogram:
SYSTEM
REM subroutines to convert R value back to standard notation
REM input R containing resistor value (with possible float errors)
REM output R$ containing value in standard resistor notation
convertE96:
R$ = "error": R2$ = "": R1 = R + .00001: R2 = R
IF R1 >= 1000 THEN R2 = R1 / 1000: R2$ = "K"
IF R1 >= 1000000 THEN R2 = R1 / 1000000: R2$ = "M"
IF R2 < 1 THEN R$ = LEFT$(LTRIM$(STR$(R2 + .00001)) + "000", 5)
IF R2 >= 1 AND R2 < 100 THEN R$ = LEFT$(LTRIM$(STR$(R2 + .00001)) + "000", 4) + R2$
IF R2 >= 100 AND R2 < 1000 THEN R$ = LEFT$(LTRIM$(STR$(R2)), 3) + R2$
RETURN
convertE24:
R$ = "error": R2$ = "": R1 = R + .00001: R2 = R
IF R1 >= 1000 THEN R2 = R1 / 1000: R2$ = "K"
IF R1 >= 1000000 THEN R2 = R1 / 1000000: R2$ = "M"
IF R2 < 1 THEN R$ = LEFT$(LTRIM$(STR$(R2 + .00001)) + "00", 4)
IF R2 >= 1 AND R2 < 10 THEN R$ = LEFT$(LTRIM$(STR$(R2 + .00001)) + "00", 3) + R2$
IF R2 >= 10 AND R2 < 100 THEN R$ = LEFT$(LTRIM$(STR$(R2)), 2) + R2$
IF R2 >= 100 AND R2 < 1000 THEN R$ = LEFT$(LTRIM$(STR$(R2)), 3) + R2$
RETURN

Terry Newton (wtn90125@yahoo.com)