| Bytes | Lang | Time | Link |
|---|---|---|---|
| 192 | JavaScript Node.js | 250923T135618Z | Fhuvi |
| 172 | APLNARS | 250910T113545Z | Rosario |
| 088 | 05AB1E | 250910T074207Z | Kevin Cr |
| 080 | Jelly | 250911T230504Z | Jonathan |
| 167 | Ruby | 250910T140731Z | Level Ri |
| 222 | R | 250910T155826Z | M-- |
| 199 | JavaScript ES6 | 250909T103734Z | Arnauld |
| 191 | Retina 0.8.2 | 250910T150544Z | Neil |
| 108 | Charcoal | 250909T234352Z | Neil |
| 300 | Google Sheets | 250909T222604Z | doubleun |
JavaScript (Node.js), 192 bytes
I tried a different approach than Arnauld's JS answer, and it turned out pretty well!
r=>t=>[(s=Math.floor(r*100)+"0")[0],s[1],(l=s.length)<3?0:l-5,t<1?3+(1/t+6)**.5|0:t>4?t%4-3:t].map(n=>"NoneSilverGoldBlackBrownRedOrangeYellowGreenBlueVioletGreyWhite".match(/.[a-z]+/g)[+n+3])
The goal was to avoid scientific notation, and use the length of the string to obtain the Multiplier.
The first and second characters correspond to the two Digits.
The Tolerance is converted through conditions and computations to avoid the length of a lookup string.
r=>t=>is the currying syntax, which is the shortest option specifically when handling 2 parameters.s=Math.floor(r*100)+"0"gets rid of the decimals bymultiplying by 100.Math.flooris mandatory because of floating points errors, and we cannot use the classic|0because some resistance values are too big and trigger an overflow. The+"0"is used to concatenate a second zero for the specific case of a resistance value of0where we'll need to access the second character. Then we store this transformed resistance value ins.s[0],s[1]extracts the first 2 characters of the previously computed string to get the two Digits(l=s.length)<3?0:l-5gives the Multiplier based on the length of the computed string. The order of colors has been adapted so that they are in order of ascending multiplier values while also keeping natural order for the first two decimals. There is a special case handled for00which is technically a shorter string than100(previously0.1), but is higher in the order of colors.t<1?3+(1/t+6)**.5|0:t>4?t%4-3:tis a mix of conditions and computations to get the Tolerance. Using our custom order of colors the problem was how to transform20 5 10 1 2 3 4 0.5 0.25 0.10 0.05into0 1 2 4 5 6 7 8 9 10 11(notice the missing3becauseBlackdoesn't have a Tolerance value).- The values
1 2 3 4are great in this order, but they correspond to colors in the middle of the reordered range so we handle it with just the finalt(and all conditions leading to it), and is increased by3later during the color translation. - The values
20 5 10need to be transformed into0 1 2, and surprinsingly we can get it by simply doing%4(and-3to counter the future increment by3). This is also why we putNoneas the first value. - The values
0.5 0.25 0.10 0.05are handled by first calculating their inverse to get ascending values, which gives2 4 10 20. This isn't very practical, but we could make them resemble the first squares4 9 16 25. So we add6to each so that they fall into the right "square ranges" without overstepping their neighbour's square ranges. This gives8 10 16 26, which is close enough! Then we calculate the square root using the classic**.5and floor the values (because they aren't really squares) with|0. We still have to offset the index by adding3, but doing it in the left of the expression avoids having parenthesis because|0has less operator priority.
- The values
the rest of the expression is the color translation using a
mapto convert each value of our prepared array. For the colors we use the usual string storage system, and a regex to separate each word starting with a caps.+nis mandatory to force the conversion to integer, and here's the long awaited+3which helps all computations (because we put three colors beforeBlackin the custom order)
APL(NARS), 172 chars
{a←(+\a∊⎕A)⊂a←'NoneSilverGoldBlackBrownRedOrangeYellowGreenBlueVioletGreyWhite'⋄b←20,10,5,0,(⍳4),.5,.25,.10,.05⋄k←⌊⍺÷10*r←⌊10⍟(⍺÷10)+0=⍺⋄a[4+⌊k÷10],a[4+10∣k],a[4+r],a[b⍳⍵]}
Input in the left in ⍺ the resistor value, and in the right in the ⍵ the percentage of tolerance.
test:
f←{a←(+\a∊⎕A)⊂a←'NoneSilverGoldBlackBrownRedOrangeYellowGreenBlueVioletGreyWhite'⋄b←20,10,5,0,(⍳4),.5,.25,.10,.05⋄k←⌊⍺÷10*r←⌊10⍟(⍺÷10)+0=⍺⋄a[4+⌊k÷10],a[4+10∣k],a[4+r],a[b⍳⍵]}
80000000000 f 1
Grey Black White Brown
0 f 1
Black Black Black Brown
0.63 f 0.05
Blue Orange Silver Grey
84000 f 1
Grey Yellow Orange Brown
0 f 4
Black Black Black Yellow
05AB1E, 88 bytes
Ð.0м0.øsgΘÛ2∍DŠ/¹_+т*T.nòͪ•c€µÖ:Ëjøz®º€8¡•₄;в20/Ikª”ƒÏŽÌ†¾›ÈŠÛˆ¨‡— Violet°¯„¸Šª‹ßˆ°”#sè
Try it online or verify all test cases.
Explanation:
Ð # Triplicate the first (implicit) input-resistance
.0 # Push ".0"
м # Remove a potential "." and all "0"s from the next copy
0.ø # Surround it with a leading/trailing 0
s # Swap to get the input-resistance at the top again
g # Pop and push its length
Θ # Do an ==1 check (1 if 1; 0 otherwise)
Û # Trim those leading digits from the string
# (aka, trim the leading added 0 if the input-length isn't 1)
2∍ # Shorten the length to a pair
# (aka, trim the trailing added 0 if the input contains two non-0 digits)
# (we now have a string of the two Digits)
D # Duplicate this string-pair of digits
Š # Triple-swap a,b,c to c,a,b
/ # Divide the remaining resistance by this pair of digits
# (we now have the Multiplier)
¹ # Push the first input-resistance again
_ # Do an ==0 check (1 if 0; 0 otherwise)
+ # Add that to the Multiplier-value
т* # Multiply by 10
T.n # Logarithm of 10
ò # Round to the nearest integer (for floating point inaccuracies)
Í # Subtract 2
ª # Convert the string-pair to a pair of digits,
# and append this value to it
•c€µÖ:Ëjøz®º€8¡• # Push compressed integer 742226680000078203187562525100400
₄; # Push 500 (1000 halved)
в # Convert the large integer to a base-500 list:
# [3,20,40,60,80,10,5,2,1,0,100,200,400]
20/ # Divide each by 20:
# [0.15,1,2,3,4,0.5,0.25,0.1,0.05,0,5,10,20]
Ik # Get the 0-based index of the second input-tolerance in this list
ª # Append it to the earlier triplet
”ƒÏŽÌ†¾›ÈŠÛˆ¨‡— Violet°¯„¸Šª‹ßˆ°”
# Push dictionary string "Black Brown Red Orange Yellow Green Blue Violet Grey White None Silver Gold"
# # Split it on spaces
s # Swap so the earlier quartet is at the top of the stack again
è # Get the strings at those indices
# (where the -1 and -2 are the last and next to last values)
# (after which the result is output implicitly)
See this 05AB1E tip of mine (sections How to use the dictionary?, How to compress large integers?, and How to compress integer lists?) to understand why •c€µÖ:Ëjøz®º€8¡• is 742226680000078203187562525100400; •c€µÖ:Ëjøz®º€8¡•₄;в is [3,20,40,60,80,10,5,2,1,0,100,200,400]; and ”ƒÏŽÌ†¾›ÈŠÛˆ¨‡— Violet°¯„¸Šª‹ßˆ°” is "Black Brown Red Orange Yellow Green Blue Violet Grey White None Silver Gold".
Jelly, 80 bytes
tŻŻ+3ṫ-;ċ
×ȷDç0ṣ13U-¦j12;“ṀdxÞ(<P½¦£¢‘÷20¤i⁹¤ị“!-WƓ®ḲTọnṾȦẊḟeż&)ÇạøN5ḤtḣḲXƓȧȯ»Ḳ¤
A dyadic Link that accepts the resistance on the left and the tolerance on the right and yields the band colours as a list of four lists of characters.
Try it online! Or see the test-suite.
How?
tŻŻ+3ṫ-;ċ - Helper Link: D=Digits of 1000×R, Y=0
t - trim {Y}s from {D}
ŻŻ - prefix with two zeros
+3 - add three to each of these
ṫ- - tail from 1-index -1 (keep the last two)
;ċ - concatenate the count of zeros in {D}
×ȷDç0ṣ13U-¦j12;“...‘÷20¤i⁹¤ị“...»Ḳ¤ - Main Link: R, T
×ȷ - multiply {R} by 1000 -> 1000R
D - get the decimal digits of that -> D
ç0 - call the Helper Link - f(D, 0)
ṣ13U-¦j12 handling edge-case R = (d×10 + 0) × 10^9:
ṣ13 - split at 13s
U-¦ - reverse the penultimate chunk
j12 - join with 12s
-> [d1+3, d2+3, MultiplierIndex]
¤ - nilad followed by link(s) as a nilad:
¤ - nilad followed by link(s) as a nilad:
“...‘ - code-page indices
-> [200,100,120,20,40,60,80,10,5,2,1]
÷20 - divide by twenty
-> [10,5,6,1,2,3,4,0.5,0.25,0.1,0.05]
i⁹ - 1-index of {T} in that, or 0 if not found (T=20)
; - concatenate
-> [d1+2, d2+2, MultiplierIndex, ThresholdIndex]
ị - 1-index, cyclically, into...
¤ - ...nilad followed by link(s) as a nilad:
“...» - "Silver Gold Black Brown Red Orange Yellow Green Blue Violet Grey White None"
Ḳ - split at spaces
Ruby, 170 167 bytes
->a,b{[0,2,9,13].map{|i|%w{Black Brown Red Orange Yellow Green Blue Violet Grey White None Silver Gold}[("%e #{"873;62:<154"[b*19%11].ord-48}"%(a/10))[i,i/4+1].to_i]}}
Eliminated variable c, used value directly. Changed decoding of tolerance colour from a magic number to a magic string. New perfect hash b*19%11 is 1 byte shorter in Ruby than a port of @Arnauld's approach but gives some floating point numbers. These are however automatically truncated to integers when used for lookup in the string.
Ruby, 176 bytes
->a,b{c="%e #{0x1234CAF5FB6F78>>(b*13%14).to_i*4&15}"%a/=10
[0,2,9,13].map{|i|%w{Black Brown Red Orange Yellow Green Blue Violet Grey White None Silver Gold}[c[i,i/4+1].to_i]}}
A function taking two numbers as arguments and returning an array of strings containing colours.
We generate a string like the below with the exponential representation of a to which we append an integer representing the correct colour of the tolerance stripe from b.
We then map through the indices [0,2,9,13] of this string, pick out an appropriate number of characters i/4+1, convert this to an integer and lookup the correct colour.
"0.000000e+00 4"
["Black", "Black", "Black", "Yellow"]
"8.400000e+03 1"
["Grey", "Yellow", "Orange", "Brown"]
"6.300000e-02 8"
["Blue", "Orange", "Silver", "Grey"]
Note that None, Silver, Gold appear in the code in reverse order than in the table in the question. This is because Ruby wraps negative indices to the end of the array. Hence -02 in the example above becomes "Silver" as this is the second last element.
There are probably better ways of decoding the index of the tolerance stripe into an integer that matches the colour scheme used by other stripes. This is the first way I came up with. I may get back to it later.
R, 268 243 227* 222 bytes
\(r,t,s=strtoi(el(strsplit(sprintf("%.1e",r),"[.e]"))),v=s[3])c(colors()[c(24,32,552,498,652,254,26,640,260,1,142)],"silver","none")[c(s[-3]+1,`if`(r<1e-9,1,13*(v<0)+v),c(2:9,11:13)[match(t,c(1:4,.5,.25,.1,.05,5,10,20))])]
* 16 bytes saved by pajonk.
JavaScript (ES6), 199 bytes
-1 thanks to @Neil
Expects (r)(t) and returns an array of 4 strings.
r=>t=>[([[x,,y],e]=r.toExponential(1).split`e`,z=r>=.1)*x,z?y:x,e-z,"0x"+"0A9C1864537"[t*20%52%11]-2].map(n=>"SilverGoldBlackBrownRedOrangeYellowGreenBlueVioletGreyWhiteNone".match(/.[a-z]+/g)[+n+2])
Color list
To make it easier to encode multipliers, the color list is reorganized as follows:
- 0 - Silver
- 1 - Gold
- 2 to 11 - Black to White
- 12 - None
Resistance value
We normalize the resistance value \$r\$ in exponential notation with one fraction digit and map the result to the variables \$x\$, \$y\$, \$e\$ (first significant digit, next digit and signed exponent respectively).
For instance:
84000 --> "8.4e+4" --> x = "8", y = "4", e = "+4"
It's encoded as:
- \$[0,0,0]\$ if \$r=0\$
- \$[0,x,-2]\$ if \$0<r<0.1\$
- \$[x,y,e-1]\$ if \$r\ge0.1\$
For each of these values, the actual color index is obtained by adding \$2\$.
Tolerance
The tolerance is first turned into an integer by multiplying it by \$20\$, then reduced to a lookup index in \$[0\dots10]\$ by applying the modulo chain \$(x \bmod 52)\bmod 11\$.
The lookup string "0A9C1864537" stores the color indexes in hexadecimal.
| Color | Tolerance | ×20 | mod 52 | mod 11 | Color index |
|---|---|---|---|---|---|
| Brown | 1 | 20 | 20 | 9 | 0x3 |
| Red | 2 | 40 | 40 | 7 | 0x4 |
| Orange | 3 | 60 | 8 | 8 | 0x5 |
| Yellow | 4 | 80 | 28 | 6 | 0x6 |
| Green | 0.5 | 10 | 10 | 10 | 0x7 |
| Blue | 0.25 | 5 | 5 | 5 | 0x8 |
| Violet | 0.1 | 2 | 2 | 2 | 0x9 |
| Grey | 0.05 | 1 | 1 | 1 | 0xA |
| Gold | 5 | 100 | 48 | 4 | 0x1 |
| Silver | 10 | 200 | 44 | 0 | 0x0 |
| None | 20 | 400 | 36 | 3 | 0xC |
Commented
r => // outer function taking r
t => // inner function taking t
[ //
( //
[[x,, // x = 1st significant digit of r as a character
y], // y = next digit as a character
e] = // e = signed exponent string (e.g. "+2")
r.toExponential(1) // extracted from r.toExponential(1) ...
.split`e`, // ... split on 'e'
z = r >= .1 // set z to true if r is greater or equal to 0.1
) * x, // 1) use x if z is set, or 0 otherwise
z ? y // 2) use y if z is set,
: x, // or x otherwise
e - z, // 3) use e - z
"0x" + // 4) hexadecimal prefix
"0A9C1864537"[ // read this lookup string at ...
t * 20 % 52 % 11 // ... the relevant index computed from t
] - 2 // subtract 2
].map(n => // for each value n computed above:
"SilverGold...None" // color lookup string
.match( // split by words
/.[a-z]+/g // (using title case)
)[+n + 2] // take the entry at index n+2
) // end of map()
Retina 0.8.2, 191 bytes
^0
00
12$*0
0?\.(.{12})0*
$1
^(.)(.)(0{12})?(0*)
$1 $2 $.4
20
None
11|\b5$
Gold
10
Silver
9
White
8|0.05
Grey
7|0.1
Violet
6|0.25
Blue
5|0.5
Green
4
Yellow
3
Orange
2
Red
1
Brown
0
Black
Try it online! Link includes test cases. Explanation:
^0
00
Add an extra 0 to a zero input so that the exponent comes out correct.
12$*0
0?\.(.{12})0*
$1
^(.)(.)(0{12})?(0*)
$1 $2 $.4
Multiply by 10¹², then capture the first two digits and reduce the exponent modulo 12. This conveniently maps -2 to 10 for Silver.
20
None
11|\b5$
Gold
10
Silver
9
White
8|0.05
Grey
7|0.1
Violet
6|0.25
Blue
5|0.5
Green
4
Yellow
3
Orange
2
Red
1
Brown
0
Black
Map each value to its colour, except that Gold is 5(%) tolerance instead of Green, and Grey to Green also match their respective tolerances.
Charcoal, 108 bytes
≔﹪%.1e∕NχθE⟦§θ⁰§θ²⊟⪪θe⌕⪪”‴|“V¶!⊘π▶α…qêZY‽≕P›” S⟧⭆§⪪”↶±!γ$~∧‖!\↧F%1/⁶fL\`κ↖!↶Φ#⁵ïδDy◨ ?jFNNωπbe!V⍘¬y↷” Iι⎇μλ↥λ
Try it online! Link is to verbose version of code. Explanation:
≔﹪%.1e∕Nχθ
Divide the first input by 10 and then convert it to exponential notation with one digit after the decimal point, e.g. 84000 converts to 8.4e+03.
E⟦§θ⁰§θ²⊟⪪θe
Map over the first character, the third character and the exponent, and also...
⌕⪪”...” S⟧
... looking up the tolerance in a compressed list split on spaces, ...
⭆§⪪”...” Iι⎇μλ↥λ
... look up each value in the compressed lowercase list of colours and uppercase the first character (this is still 3 bytes shorter overall than using proper case in the list of colours).
The compressed list of colours ends with none silver gold as this allows for cyclic indexing for exponents of -1 and -2.
Google Sheets, 300 bytes
=sort(let(f,lambda(k,n,xlookup(k,n,tocol(split("Black0Brown0Red0Orange0Yellow0Green0Blue0Violet0Grey0White0Gold0Silver0None",0)))),g,lambda(n,index(split(text(A1,"0.0#e+0"),".e"),n)),{f({g(1),g(2),if(g(3)=-1,11,g(3)-(g(1)>0))},row(1:13)-1),f(B1,tocol(split("919293949.59.259.19.05995910920",9,,)))}))
Put resistance in A1 and tolerance in B1. Outputs four strings.

This matches all current test cases but doesn't observe what's said in the question's comments.
Ungolfed:
=arrayformula(let(
c, tocol(split("Black0Brown0Red0Orange0Yellow0Green0Blue0Violet0Grey0White0Gold0Silver0None", 0)),
m, tocol(split(",1,2,3,4,.5,.25,.1,.05,,5,10,20", ",",,)),
i, sequence(13) - 1,
f, lambda(k, n, xlookup(k, n, c)),
g, lambda(n, index(split(text(A1, "0.0#e+0"), ".e"), n)),
{ f({ g(1), g(2), if(g(3) = -1, 11, g(3) - (g(1) > 0)) }, i), f(B1, m) }
))