Problem:
Problem D: 単位変換器

国際単位系(SI)では、kilo, mega, giga などの接頭辞を使って、「数値 + 接頭辞 + 単位」という形でさまざまな物理量を表記する。たとえば、「3.5 kilometers」, 「5.1 milligrams」 といった具合である。

一方、これらの物理量は指数表記を使って「3.5 * 10^3 meters」、「5.1 * 10^-3 grams」のように表すことも可能である。

物理量の測定は必ず誤差を含む。そこで、測定された物理量がどれだけの精度を持つかを表すために、有効数字という概念がある。有効数字を考慮した表記では、最後の桁は誤差を含みうるが、それ以外の桁は信頼できるものと考える。たとえば、「1.23」 と表記した場合、真の値は 1.225 以上 1.235 未満であり、小数第1位以上の桁は信頼できるが、小数第2位には誤差を含む。このように「信頼できる桁 + 誤差を含む1桁」という形で物理量を表したときの桁数を有効桁数と呼ぶ。たとえば、「1.23」の有効桁数は3桁である。

0でない最上位の桁より前に0がある場合、その0は有効桁数には含めない。たとえば、「0.45」の有効桁数は2桁である。 0でない最下位の桁より後に0がある場合、その0を有効桁数に含むかどうかは小数点の位置により異なる。小数点より右まで0があるときは、その0は有効桁数に含める。たとえば、「12.300」の有効桁数は5桁である。一方、「12300」のように、小数点より右に0がないときは、右側の0を有効桁数に含めるかどうかは明確ではないが、この問題においては含めることとする。すなわち、「12300」の有効桁数は5桁である。

なつめは学校の課題で物理の問題を出された。その中で有効数字や単位が関わる計算をしなければならないのだが、困ったことになつめには有効数字や単位の使い方がまだよくわかっていない。そこで、自動でそれらの計算をするプログラムを作って、なつめを助けてあげてほしい。

あなたが書くのは、接頭辞を使った表記が与えられたとき、それを有効桁数が等しい指数表記に変換するプログラムである。使われる接頭辞は以下の20個である。

yotta = 10^24

zetta = 10^21

exa = 10^18

peta = 10^15

tera = 10^12

giga = 10^9

mega = 10^6

kilo = 10^3

hecto = 10^2

deca = 10^1

deci = 10^-1

centi = 10^-2

milli = 10^-3

micro = 10^-6

nano = 10^-9

pico = 10^-12

femto = 10^-15

ato = 10^-18

zepto = 10^-21

yocto = 10^-24

Input

入力は1行のみからなり、その唯一の行には、数値、（もしあれば）単位接頭辞、単位が含まれている。それぞれの間は空白1個で区切られている。単位接頭辞がない場合もあり、その場合は数値と単位のみが行に含まれる。単位接頭辞と同じ名前の単位は現れない。小数が与えられる場合の1の位を除き、最上位の桁が0になることはない。与えられる数値は正である。与えられる数値は小数点を含め1000桁以下で、単位の名前は50文字以下である。

Output

a * 10^b [単位] の形で指数表記で表現された量を出力せよ。ただし、1 <= a < 10 である。単位名の単数形・複数形の違いは考慮しない。入力に与えられた単位名をそのまま出力せよ。

Notes on Submission

上記形式で複数のデータセットが与えられます。入力データの 1 行目にデータセットの数が与えられます。各データセットに対する出力を上記形式で順番に出力するプログラムを作成して下さい。

Sample Input

7
12.3 kilo meters
0.45 mega watts
0.000000000000000000000001 yotta grams
1000000000000000000000000 yocto seconds
42 amperes
0.42 joules
1234.56789012345678901234567890 hecto pascals

Output for the Sample Input

1.23 * 10^4 meters
4.5 * 10^5 watts
1 * 10^0 grams
1.000000000000000000000000 * 10^0 seconds
4.2 * 10^1 amperes
4.2 * 10^-1 joules
1.23456789012345678901234567890 * 10^5 pascals

Solution in C# (judge verdict: Accepted)

using System.Collections.Generic;
using System;

public class P
{
    public string a { get; set; }
    public int b { get; set; }
}

public class Hello
{
    public static void Main()
    {
        var d1 = new string[] { "yotta", "zetta", "exa", "peta", "tera", "giga", "mega",
            "kilo", "hecto", "deca", "deci", "centi", "milli", "micro", "nano", "pico", "femto",
            "ato", "zepto", "yocto" };
        var d2 = new int[] { 24, 21, 18, 15, 12, 9, 6, 3, 2, 1, -1, -2, -3, -6, -9, -12, -15, -18, -21, -24 };
        var d = new Dictionary<string, int>();
        for (int i = 0; i < d1.Length; i++) d[d1[i]] = d2[i];
        var n = int.Parse(Console.ReadLine().Trim());
        for (int i = 0; i < n; i++)
        {
            string[] line = Console.ReadLine().Trim().Split(' ');
            var ret = getAns(line[0]);
            if (d.ContainsKey(line[1]))
            {
                var w = ret.b + d[line[1]];
                Console.WriteLine("{0} * 10^{1} {2}", ret.a, w, line[2]);
            }
            else Console.WriteLine("{0} * 10^{1} {2}", ret.a, ret.b, line[1]);
        }
    }
    public static P getAns(string s)
    {
        var ret = "";
        var sL = s.Length;
        var si = s.IndexOf('.');
        if (si == -1)
        {
            if (sL == 1) return new P { a = s, b = 1 };
            ret = s.Substring(0, 1) + "." + s.Substring(1);
            return new P { a = ret, b = sL - 1 };
        }
        else if (s.Substring(0, 2) == "0.")
        {
            var first = true; var count = 0;
            for (int i = 2; i < sL; i++)
            {
                if (s[i] == '0' && first) count++;
                else if (s[i] == '0' && !first) ret += s[i].ToString();
                else if (s[i] != '0' && first) { ret += s[i].ToString() + "."; first = false; }
                else { ret += s[i]; first = false; }
            }
            if (ret[ret.Length - 1] == '.') ret = ret.Replace(".", "");
            return new P { a = ret, b = -count - 1 };
        }
        else
        {
            var w = s.Replace(".", "");
            ret = w.Substring(0, 1) + "." + w.Substring(1);
            return new P { a = ret, b = si - 1 };
        }
    }
}