在Java中自动将测量值格式化为工程单位

5
我正在寻找一种自动将测量值和单位格式化为工程符号中的字符串的方法。这是科学记数法的特殊情况,因为指数始终是三的倍数,但使用千、兆、毫、微等前缀表示。
这类似于此帖子,但它应该处理整个SI单位和前缀范围。
例如,我需要一个库来格式化量,使得: 12345.6789 Hz 格式化为 12 kHz 或 12.346 kHz 或 12.3456789 kHz 1234567.89 J 格式化为 1 MJ 或 1.23 MJ 或 1.2345 MJ 等等。
JSR-275 / JScience 可以处理单位测量,但我还没有找到可以根据测量值的大小自动确定最适当缩放前缀的东西。
干杯, Sam.

这似乎是一个简单的地方来实现自己的代码。唯一棘手的部分是处理像质量这样的数量,其中国际单位制已经有了公制前缀。 - Anon.
@Anon 如果你让它以克为单位思考,即使这不是正确的国际单位制,计算质量也可能会更容易。 - corsiKa
1个回答

6
import java.util.*;
class Measurement {
    public static final Map<Integer,String> prefixes;
    static {
        Map<Integer,String> tempPrefixes = new HashMap<Integer,String>();
        tempPrefixes.put(0,"");
        tempPrefixes.put(3,"k");
        tempPrefixes.put(6,"M");
        tempPrefixes.put(9,"G");
        tempPrefixes.put(12,"T");
        tempPrefixes.put(-3,"m");
        tempPrefixes.put(-6,"u");
        prefixes = Collections.unmodifiableMap(tempPrefixes);
    }

    String type;
    double value;

    public Measurement(double value, String type) {
        this.value = value;
        this.type = type;
    }

    public String toString() {
        double tval = value;
        int order = 0;
        while(tval > 1000.0) {
            tval /= 1000.0;
            order += 3;
        }
        while(tval < 1.0) {
            tval *= 1000.0;
            order -= 3;
        }
        return tval + prefixes.get(order) + type;
    }

    public static void main(String[] args) {
        Measurement dist = new Measurement(1337,"m"); // should be 1.337Km
        Measurement freq = new Measurement(12345678,"hz"); // should be 12.3Mhz
        Measurement tiny = new Measurement(0.00034,"m"); // should be 0.34mm

        System.out.println(dist);
        System.out.println(freq);
        System.out.println(tiny);

    }

}

请注意,“kilo”应为小写k。此外,我相信您想要的是“340微米”(而不是0.34毫米),因此您的第二个循环应该是while(tval < 1) - Anon.
我明白了,我会加上这些内容。我原本以为小数点后3位以内的任何值都可以。看来我们希望组件的值在1 <= c < 1000之间。感谢您的澄清!我也将u添加到了映射中(即使它不是确切的字母,但应该可以工作)。 - corsiKa
用户(Xp-ert)的评论:如果值tval不等于0,则在while(tval > 1000.0) {之前添加if(tval != 0) {,并在return tval + prefixes.get(order) + type;之前添加},否则当值为0时应用程序将永久循环。 - Anne
@Anne 我明白你的意思。是的,零是一个特殊情况。我认为,我们应该建立一个足够接近零的范围,而不是将其设为0,这样我们就可以称之为0,而不是直接与0进行比较。我还想将我的前缀列表扩展到阈值以下,以便覆盖所有输入。 - corsiKa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接