开发者

"Intelligent" cast of double to two differently formatted strings?

开发者 https://www.devze.com 2022-12-10 09:40 出处:网络
I\'m working with a database that has the limit that the only (numeric) datatype it can store is 开发者_StackOverflow中文版a double. What I want to do is pick the number for a certain row and put it i

I'm working with a database that has the limit that the only (numeric) datatype it can store is 开发者_StackOverflow中文版a double. What I want to do is pick the number for a certain row and put it into an HTTP request. The problem revolves around that I cannot know if this number should or should not have decimals.

For example, if the double is an ID, I cannot have any kind of formatting whatsoever, since the site that gets the HTTP request will be confused. Observe the following examples:

site.com/showid.php?id=12300000 // OK
site.com/showid.php?id=1.23E7 // Bad; scientific notation
site.com/showid.php?id=12300000.0 // Bad; trailing decimal

The solution to this would be to cast it to a long. Ignoring the problem of overflowing the long, it solves the scientific notation and (obviously) trailing decimal. This could be an acceptable solution but it would be nice if the code didn't assume it were IDs we were dealing with. What if, for example, I were to query a site that shows a map and the number are coordinates, where the decimals are very important? Then a cast to long is no longer acceptable.

In short;

  • If the double has no decimals, do not add a trailing decimal.
  • If it has decimals, keep them all.
  • Neither case should have scientific notation or thousand separators.

This solution will be ported to both C# and Java so I accept answers in both languages. (Oh, and I had no idea what to call this question, feel free to rename if you got something better.)


To complement the answer of gustafc (who beat me by 1 minute), here's the relevant code line for C#:

MyDouble.ToString("0.################")

or

string.Format("{0:0.################}", MyDouble);


Since it is safe to format the value with no trailing zeroes if it is integral (whether it represents an ID or a coordinate), why not just codify the logic you describe in your bullet points? For example (C#, but should translate readily to Java):

// Could also use Math.Floor, etc., to determine if it is integral
long integralPart = (long)doubleValue;
if ((double)integralPart == doubleValue)
{
  // has no decimals: format it as an integer e.g. integralPart.ToString("D") in C#
}
else
{
  // has decimals: keep them all e.g. doubleValue.ToString("F17")
}


How about encapsulating the number in a custom type?

public class IntelligentNumber
{
    private readonly double number;

    public IntelligentNumber(double number)
    {
        this.number = number;
    }

    public override string ToString()
    {
        long integralPart = (long)this.number;
        if((double)integralPart == this.number)
        {
            return integralPart.ToString();
        }
        else
        {
            return this.number.ToString();
        }
    }
}

See also Vilx-'s answer for a better algorithm than the one above.


check whether num == round(num)


In Java, you can do this with DecimalFormat.

static String format(double n) { 
    return new DecimalFormat("0.###########################").format(n); 
}

The # placeholders won't show up unless the number something other than zeros to put there, and the decimal point doesn't show up unless there's something following it.


Heres my own conclusion:

  • Check if the double has decimals.
  • Depending on that, format the string accordingly.
  • And then something important; without specifying an invariant culture, the comma in the has-decimals case may be a "," instead of a "." which isnt liked by HTTP requests. Of course, this problem only crops up if your OS is set to a locale that prefers the comma.

    public static string DoubleToStringFormat(double dval)
    {
        long lval = (long)dval;
        if ((double)lval == dval)
        {
            // has no decimals: format as integer
            return dval.ToString("#.", CultureInfo.InvariantCulture);
        }
        else
        {
            // has decimals: keep them all
            return dval.ToString("0.##################", CultureInfo.InvariantCulture);
        }
    }
    
0

精彩评论

暂无评论...
验证码 换一张
取 消