From 8a8651404bd8ed187bcaedfef2948e7835aea318 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Tue, 17 May 2022 11:29:44 -0700 Subject: Automatically finding E-series matches and metric prefixes --- lace.rb | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'lace.rb') diff --git a/lace.rb b/lace.rb index ef9a97e..b5aebf1 100644 --- a/lace.rb +++ b/lace.rb @@ -1,7 +1,89 @@ +require "bigdecimal" require "set" module Lace + PREFIXES = { + "femto" => 10**-15, + "f" => 10**-15, + "pico" => 10**-12, + "p" => 10**-12, + "nano" => 10**-9, + "n" => 10**-9, + "micro" => 10**-6, + "u" => 10**-6, + "ยต" => 10**-6, + "milli" => 10**-3, + "m" => 10**-3, + "" => 10**0, + "kilo" => 10**3, + "k" => 10**3, + "mega" => 10**6, + "M" => 10**6, + } + + def self.number(num) + num = num.to_s + PREFIXES.each do | p, d | + if num =~ /^(.+)#{p}$/i + begin + num = BigDecimal($1) * d + break + rescue ArgumentError + end + end + end + num = BigDecimal(num) unless num.instance_of?(BigDecimal) + return "0" if num == 0 + prefix = "f" + div = PREFIXES["f"] + PREFIXES.each do | p, d | + if num.abs >= d and d >= div and (d > div or p.size < prefix.size or (p.size == prefix.size and p > prefix)) + prefix = p + div = d + end + end + num /= div + num = num.to_s("F") + num.sub!(/\.0$/, "") + return "#{num}#{prefix}" + end + + E3 = [10, 22, 47] + E6 = E3 + [15, 33, 68] + E12 = E6 + [12, 18, 27, 39, 56, 82] + E24 = E12 + [11, 13, 16, 20, 24, 30, 36, 43, 51, 62, 75, 91] + + E48 = [100, 105, 110, 115, 121, 127, 133, 140, 147, 154, 162, 169, 178, 187, 196, 205, 215, 226, 237, 249, 261, 274, 287, 301, 316, 332, 348, 365, 383, 402, 422, 442, 464, 487, 511, 536, 562, 590, 619, 649, 681, 715, 750, 787, 825, 866, 909, 953] + E96 = E48 + [102, 107, 113, 118, 124, 130, 137, 143, 150, 158, 165, 174, 182, 191, 200, 210, 221, 232, 243, 255, 267, 280, 294, 309, 324, 340, 357, 374, 392, 412, 432, 453, 475, 499, 523, 549, 576, 604, 634, 665, 698, 732, 768, 806, 845, 887, 931, 976] + E192 = E96 + [101, 104, 106, 109, 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 142, 145, 149, 152, 156, 160, 164, 167, 172, 176, 180, 184, 189, 193, 198, 203, 208, 213, 218, 223, 229, 234, 240, 246, 252, 258, 264, 271, 277, 284, 291, 298, 305, 312, 320, 328, 336, 344, 352, 361, 370, 379, 388, 397, 407, 417, 427, 437, 448, 459, 470, 481, 493, 505, 517, 530, 542, 556, 569, 583, 597, 612, 626, 642, 657, 673, 690, 706, 723, 741, 759, 777, 796, 816, 835, 856, 876, 898, 920, 942, 965, 988] + + def self.nearest(num, set) + return BigDecimal(0) if num == 0 + base = set.min + exp = Math.log10(base).round + numexp = Math.log10(num).floor + num = num * 10**(exp-numexp) + candidate = nil + delta = Float::INFINITY + set.each do | c | + d = (num - c).abs + if d < delta + candidate = c + delta = d + end + end + return BigDecimal(candidate * 10**(numexp-exp), exp+1) + end + + def self.e3(num); nearest(num, E3); end + def self.e6(num); nearest(num, E6); end + def self.e12(num); nearest(num, E12); end + def self.e24(num); nearest(num, E24); end + def self.e48(num); nearest(num, E48); end + def self.e96(num); nearest(num, E96); end + def self.e192(num); nearest(num, E192); end + class Netlist attr_reader :components -- cgit v1.2.3