|
1 |
| -# Convert numbers to engineering and SI units |
2 |
| - |
3 |
| -# Copyright © 2015 Kevin Thibedeau |
4 |
| -# (kevin 'period' thibedeau 'at' gmail 'punto' com) |
5 |
| -# |
6 |
| -# Permission is hereby granted, free of charge, to any person obtaining a |
7 |
| -# copy of this software and associated documentation files (the "Software"), |
8 |
| -# to deal in the Software without restriction, including without limitation |
9 |
| -# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
10 |
| -# and/or sell copies of the Software, and to permit persons to whom the |
11 |
| -# Software is furnished to do so, subject to the following conditions: |
12 |
| -# |
13 |
| -# The above copyright notice and this permission notice shall be included in |
14 |
| -# all copies or substantial portions of the Software. |
15 |
| -# |
16 |
| -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 |
| -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 |
| -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 |
| -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 |
| -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 |
| -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
22 |
| -# DEALINGS IN THE SOFTWARE. |
23 |
| - |
24 |
| -import strutils, sequtils, tables, math |
25 |
| - |
26 |
| - |
27 |
| -type engPair = tuple[num: float, exp: int] |
28 |
| - |
29 |
| -proc toEng(f: float): engPair = |
30 |
| - |
31 |
| - let logVal = log10(abs(f)) |
32 |
| - var exp = if classify(logVal) != fcNegInf: logVal.int else: 1 |
33 |
| - |
34 |
| - if exp < -24: |
35 |
| - exp = -24 |
36 |
| - |
37 |
| - var r : engPair |
38 |
| - |
39 |
| - r.exp = exp - exp mod 3 |
40 |
| - |
41 |
| - if r.exp <= 0 and f < (10.0.pow(r.exp.float)-0.00000001): |
42 |
| - r.exp -= 3 |
43 |
| - |
44 |
| - r.num = f / 10.0.pow(r.exp.float) |
45 |
| - |
46 |
| - result = r |
47 |
| - |
48 |
| - |
49 |
| -proc formatEng*(f: float, fracDigits: Natural = 1): string = |
50 |
| - let ep = toEng(f) |
51 |
| - var digits: string |
52 |
| - if fracDigits > 0: |
53 |
| - digits = formatFloat(ep.num, ffDecimal, fracDigits) |
54 |
| - else: |
55 |
| - digits = $ep.num.round |
56 |
| - |
57 |
| - result = digits & "e" & $ep.exp |
58 |
| - |
59 |
| - |
60 |
| -const siPrefixes = { |
61 |
| - 21: "Y", |
62 |
| - 18: "Z", |
63 |
| - 15: "E", |
64 |
| - 12: "P", |
65 |
| - 9: "G", |
66 |
| - 6: "M", |
67 |
| - 3: "k", |
68 |
| - 0: "", |
69 |
| - -3: "m", |
70 |
| - -6: "u", |
71 |
| - -9: "n", |
72 |
| - -12: "p", |
73 |
| - -15: "f", |
74 |
| - -18: "a", |
75 |
| - -21: "z", |
76 |
| - -24: "y" |
77 |
| -}.toTable |
78 |
| - |
79 |
| -proc formatSI*(f: float, units: string, fracDigits: Natural = 1, unitSep = " "): string = |
80 |
| - let ep = toEng(f) |
81 |
| - var digits: string |
82 |
| - if fracDigits > 0: |
83 |
| - digits = formatFloat(ep.num, ffDecimal, fracDigits) |
84 |
| - else: |
85 |
| - digits = $ep.num.round |
86 |
| - |
87 |
| - var strExp: string |
88 |
| - if siPrefixes.hasKey(ep.exp): |
89 |
| - strExp = unitSep & siPrefixes[ep.exp] & units |
90 |
| - else: |
91 |
| - strExp = "e" & $ep.exp |
92 |
| - |
93 |
| - result = digits & strExp |
94 |
| - |
95 |
| -when isMainModule: |
96 |
| - #var x = newSIEng(42.0e-5, "s") |
97 |
| - |
98 |
| - echo "Result: ", formatEng(42.0e-5) |
99 |
| - echo "toSI: ", formatSI(32.0e-10, "F") |
100 |
| - |
101 |
| - |
| 1 | +# Convert numbers to engineering and SI units |
| 2 | + |
| 3 | +# Copyright © 2015 Kevin Thibedeau |
| 4 | +# (kevin 'period' thibedeau 'at' gmail 'punto' com) |
| 5 | +# |
| 6 | +# Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | +# copy of this software and associated documentation files (the "Software"), |
| 8 | +# to deal in the Software without restriction, including without limitation |
| 9 | +# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 10 | +# and/or sell copies of the Software, and to permit persons to whom the |
| 11 | +# Software is furnished to do so, subject to the following conditions: |
| 12 | +# |
| 13 | +# The above copyright notice and this permission notice shall be included in |
| 14 | +# all copies or substantial portions of the Software. |
| 15 | +# |
| 16 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 19 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 21 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 22 | +# DEALINGS IN THE SOFTWARE. |
| 23 | + |
| 24 | +import strutils, sequtils, tables, math |
| 25 | + |
| 26 | + |
| 27 | +type engPair = tuple[num: float, exp: int] |
| 28 | + |
| 29 | +proc toEng(f: float): engPair = |
| 30 | + |
| 31 | + let logVal = log10(abs(f)) |
| 32 | + var exp = if classify(logVal) != fcNegInf: logVal.int else: 1 |
| 33 | + |
| 34 | + if exp < -24: |
| 35 | + exp = -24 |
| 36 | + |
| 37 | + var r : engPair |
| 38 | + |
| 39 | + r.exp = exp - exp mod 3 |
| 40 | + |
| 41 | + if r.exp <= 0 and f < (10.0.pow(r.exp.float)-0.00000001): |
| 42 | + r.exp -= 3 |
| 43 | + |
| 44 | + r.num = f / 10.0.pow(r.exp.float) |
| 45 | + |
| 46 | + result = r |
| 47 | + |
| 48 | + |
| 49 | +proc formatEng*(f: float, fracDigits: Natural = 1): string = |
| 50 | + let ep = toEng(f) |
| 51 | + var digits: string |
| 52 | + if fracDigits > 0: |
| 53 | + digits = formatFloat(ep.num, ffDecimal, fracDigits) |
| 54 | + else: |
| 55 | + digits = $ep.num.round |
| 56 | + |
| 57 | + result = digits & "e" & $ep.exp |
| 58 | + |
| 59 | + |
| 60 | +const siPrefixes = { |
| 61 | + 21: "Y", |
| 62 | + 18: "Z", |
| 63 | + 15: "E", |
| 64 | + 12: "P", |
| 65 | + 9: "G", |
| 66 | + 6: "M", |
| 67 | + 3: "k", |
| 68 | + 0: "", |
| 69 | + -3: "m", |
| 70 | + -6: "u", |
| 71 | + -9: "n", |
| 72 | + -12: "p", |
| 73 | + -15: "f", |
| 74 | + -18: "a", |
| 75 | + -21: "z", |
| 76 | + -24: "y" |
| 77 | +}.toTable |
| 78 | + |
| 79 | +proc formatSI*(f: float, units: string, fracDigits: Natural = 1, unitSep = " "): string = |
| 80 | + let ep = toEng(f) |
| 81 | + var digits: string |
| 82 | + if fracDigits > 0: |
| 83 | + digits = formatFloat(ep.num, ffDecimal, fracDigits) |
| 84 | + else: |
| 85 | + digits = $ep.num.round |
| 86 | + |
| 87 | + var strExp: string |
| 88 | + if siPrefixes.hasKey(ep.exp): |
| 89 | + strExp = unitSep & siPrefixes[ep.exp] & units |
| 90 | + else: |
| 91 | + strExp = "e" & $ep.exp |
| 92 | + |
| 93 | + result = digits & strExp |
| 94 | + |
| 95 | +when isMainModule: |
| 96 | + #var x = newSIEng(42.0e-5, "s") |
| 97 | + |
| 98 | + echo "Result: ", formatEng(42.0e-5) |
| 99 | + echo "toSI: ", formatSI(32.0e-10, "F") |
| 100 | + |
| 101 | + |
0 commit comments