0

我们被告知在不使用 parse double 或任何 math、int 或 double 函数的情况下将字符串转换为 double。我很难使用指数转换数字。

public class Convert {

    public static void main(String args[]) {
        String num = "1223.230";
        int d = 0, g = 0, c = 0, fnl = 0;
        int exp = (num.indexOf(".") - 1);
        while (num.charAt(d) != '.') {
            g = num.charAt(d) - 48;
            int k = 1;
            for (int f = 0; f < exp; f++) {
                k = (k * 10) * g;
            }
            fnl += k;
            d++;
            exp--;
            System.out.println(fnl);                
        }   
    }

}

这些代码只转换给定字符串的 int 部分并打印错误的答案。

4

4 回答 4

2

您可以拆分“。”,然后遍历左侧,获取下一个字符数字,如果现有值 > 0,将其乘以 10,然后添加读取数字(使用开关/大小写)。你最终会增加左边的数字。

然后处理'.'的右侧。通过从右到左并做同样的事情,除了这次除以 10 并添加 digit/10。您将向右增加小数点。

最后,取左侧并将其添加到右侧。

于 2013-09-13T13:56:37.030 回答
1

我建议您在调试器中单步调试代码,看看它到底在做什么。但是我可以看到

k=(k*10)*g;

应该

k=k*10 + g;

并且k应该是long循环之外的。

您也不需要使用 indexOf。

您需要编写一个读取整数的循环。您不需要在 . 或者做任何特别的事情,只要记住它在哪里。完成后除以 10^count。

这是我写的一个方法

@Override
public double parseDouble() {
    long value = 0;
    int exp = 0;
    boolean negative = false;
    int decimalPlaces = Integer.MIN_VALUE;
    while (true) {
        byte ch = readByte();
        if (ch >= '0' && ch <= '9') {
            while (value >= MAX_VALUE_DIVIDE_10) {
                value >>>= 1;
                exp++;
            }
            value = value * 10 + (ch - '0');
            decimalPlaces++;
        } else if (ch == '-') {
            negative = true;
        } else if (ch == '.') {
            decimalPlaces = 0;
        } else {
            break;
        }
    }

    return asDouble(value, exp, negative, decimalPlaces);
}

对于这个类https://github.com/OpenHFT/Java-Lang/blob/master/lang/src/main/java/net/openhft/lang/io/AbstractBytes.java

注意:这不处理e或十六进制p表示法。

于 2013-09-13T13:58:01.140 回答
0

甲骨文就是这样做的:)

http://docs.oracle.com/javase/6/docs/api/java/lang/Double.html#valueOf(java.lang.String)

final String Digits     = "(\\p{Digit}+)";
final String HexDigits  = "(\\p{XDigit}+)";
// an exponent is 'e' or 'E' followed by an optionally 
// signed decimal integer.
final String Exp        = "[eE][+-]?"+Digits;
final String fpRegex    =
            ("[\\x00-\\x20]*"+  // Optional leading "whitespace"
             "[+-]?(" + // Optional sign character
             "NaN|" +           // "NaN" string
             "Infinity|" +      // "Infinity" string

// A decimal floating-point string representing a finite positive
// number without a leading sign has at most five basic pieces:
// Digits . Digits ExponentPart FloatTypeSuffix
// 
// Since this method allows integer-only strings as input
// in addition to strings of floating-point literals, the
// two sub-patterns below are simplifications of the grammar
// productions from the Java Language Specification, 2nd 
// edition, section 3.10.2.

// Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
             "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+

// . Digits ExponentPart_opt FloatTypeSuffix_opt
             "(\\.("+Digits+")("+Exp+")?)|"+

// Hexadecimal strings
       "((" +
// 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
        "(0[xX]" + HexDigits + "(\\.)?)|" +

// 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
        "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +

        ")[pP][+-]?" + Digits + "))" +
             "[fFdD]?))" +
             "[\\x00-\\x20]*");// Optional trailing "whitespace"

if (Pattern.matches(fpRegex, myString))
    Double.valueOf(myString); // Will not throw NumberFormatException
else
{
    // Perform suitable alternative action
}

如果您愿意,可以查看其他正则表达式模式来执行此操作,有很多。

编辑:

更漂亮的模式版本:)

private static final Pattern DOUBLE_PATTERN = Pattern
        .compile("[\\x00-\\x20]*[+-]?(NaN|Infinity|((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)"
            + "|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)"
            + "?(\\.)(\\p{XDigit}+)))[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*");
于 2013-09-13T13:56:32.170 回答
0

这只是一个解决问题的练习,因为不会真正手动执行此操作。在面试的情况下更有可能被问到。因此,正如上面的 CodeChimp 所解释的那样,最好的方法是使用好的旧单位,十、百,并在整数侧乘以在小数侧除。

 public double convertStrToDouble(String doubleAsString) {
    final String[] split = doubleAsString.split("\\."); // 123.375
    int intPart = 0;
    final String intPartStr = split[0]; // 123
    final String decPartStr = split[1]; // 375
    // (1 * 3) + (2 * 10) + (3 * 100) = 123
    int units = 1;
    for(int i = intPartStr.length()-1; i >= 0; i--) {
        char nChar = intPartStr.charAt(i);
        int n = Character.getNumericValue(nChar);
        int toAdd =  n * units;
        intPart = intPart + toAdd;
        System.out.printf("int: n %,5d toAdd %,5d intPart %,5d units %,5d\n",n,toAdd,intPart,units);
        units =  units * 10;
    }
    System.out.println("");
    // double part 375
    // (1 / 10) * 3 + (1 / 100) * 7 + (1 /1000) * 5
    // 0.3 + 0.07 + 0.005 = 0.375
    double decPart = 0d;
    units = 10;
    for(final char character : decPartStr.toCharArray()) {
        int n = Character.getNumericValue(character);
        double toAdd = (1.0 / units) * n;
        decPart = decPart + toAdd;
        System.out.printf("dec: n %,5d toAdd %,5.4f decPart %,5.4f units 1/%d\n",n,toAdd,decPart,units);
        units =  units * 10;
    }
    System.out.printf("returning %,4d + %,4.4f\n\n",intPart,decPart);
    return  intPart  + decPart;
}
于 2020-07-30T07:57:21.750 回答