Convert between SI prefixes
JavaScript (ES7), 113 109 bytes
s=>(p=s.split` `)[m={f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21},0]/(10**(m[p[3][0]]-m[p[1][0]]))
Edit: Apparently we can use µ
(U+00B5 MICRO SIGN
) for the micro sign now, so replacing with that saves a byte.
For ES6 compatibility (10**(m[p[3][0]]-m[p[1][0]]))
can be replaced with Math.pow(10,m[p[3][0]]-m[p[1][0]])
for 114 bytes.
Explanation
s=> // s = input string
(p=s.split` `) // p = input parts
// m = dictionary of SI prefix digit powers of 10
// the exact values don't matter as long as they are relative to each other
[m={f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21},
0] // get the number
/(10**(m[p[3][0]]-m[p[1][0]])) // get the factor to divide by from the difference
// between the SI prefix powers of 10
Test
This test uses Math.pow
instead of **
so that common browsers can test it.
<input type="text" id="input" value="2000 MB to GB" /><button onclick="result.innerHTML=(
s=>(p=s.split` `)[m={f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21},0]/Math.pow(10,m[p[3][0]]-m[p[1][0]])
)(input.value)">Go</button><pre id="result"></pre>
Ruby (2.2.1), 126 123 bytes
r={f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21};p ($*[0].to_r/10**(r[$*[3][0].to_sym]-r[$*[1][0].to_sym])).to_f
Saved 3 bytes thanks to user81655
Explanation
# Hash of prefixes to relative powers
r={f:-9,p:-6,n:-3,µ:0,m:3,c:4,h:8,k:9,M:12,G:15,T:18,P:21};
p ( # print (inspect)
$*[0].to_r # input value
/ 10 ** ( # divided by 10^...
r[$*[3][0].to_sym] # first prefix symbol
-
r[$*[1][0].to_sym] # second prefix symbol
)
).to_f # convert to float for proper format on output
Takes input from the command line e.g ruby si.rb 1 nm to μm
This is my first golf!
Haskell, 143 bytes
Call s
.
import Data.List
s=i.words
i(n:f:_:[t])=read n*10**(x f-x t)
x=j.flip elemIndex"f p n µ mc hk M G T P".head
j(Just n)=fromIntegral n