«Интеллектуальное» преобразование double в две строки с разным форматированием?
-
06-07-2019 - |
Вопрос
Я работаю с базой данных, которая имеет ограничение, только (числовой) тип данных он может хранить двойной.Я хочу выбрать номер для определенной строки и поместить его в HTTP-запрос.Проблема заключается в том, что я не могу знать, должно или не должно быть в этом числе десятичные дроби.
Например, если дубль является идентификатором, у меня не может быть никакого форматирования, поскольку сайт, который получает HTTP-запрос будет в замешательстве.Обратите внимание на следующие примеры:
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
Решением этой проблемы могло бы стать забросить это на длинный.Игнорируя проблему переполнения длинного числа, он решает научную запись и (очевидно) конечную десятичную дробь.Это могло бы быть приемлемым решением, но было бы неплохо, если бы код не предполагал, что мы имеем дело с идентификаторами.Что, если бы, например, я запросил сайт, на котором показана карта, а число — это координаты? где десятичные дроби очень важны? Тогда приведение к long становится неприемлемым.
Суммируя;
- Если в двойном числе нет десятичных знаков, не добавляйте конечный десятичный знак.
- Если в нем есть десятичные дроби, сохраните их все.
- Ни в одном случае не должно быть экспоненциального обозначения или разделителей тысяч.
Это решение будет портировано как на C#, так и на Java, поэтому я принимаю ответы на обоих языках.(О, я понятия не имел, как назвать этот вопрос, не стесняйтесь переименовывать, если у вас есть что-то получше.)
Решение 6
Вот мой собственный вывод:
- Проверьте, есть ли в двойном числе десятичные дроби.
- В зависимости от этого отформатируйте строку соответствующим образом.
И затем что-то важное;Без указания инвариантной культуры запятая в деле о том, что есть, может быть «», вместо «». что не нравится HTTP -запросам.Конечно, эта проблема возникает только в том случае, если в вашей ОС выбрана локаль, предпочитающая запятую.
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); } }
Другие советы
В дополнение к ответу gustafc (который опередил меня на 1 минуту), вот соответствующая строка кода для C#:
MyDouble.ToString("0.################")
или
string.Format("{0:0.################}", MyDouble);
Поскольку безопасно форматировать значение без конечных нулей, если оно является целым (независимо от того, представляет ли оно идентификатор или координату), почему бы просто не кодифицировать логику, которую вы описываете, в своих пунктах списка?Например (C#, но его следует легко перевести на 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")
}
Как насчет инкапсуляции числа в специальный тип?
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();
}
}
}
См. также ответ Vilx- для лучшего алгоритма, чем приведенный выше.
проверьте, является ли num == round(num)
В Java вы можете сделать это с помощью Десятичный формат.
static String format(double n) {
return new DecimalFormat("0.###########################").format(n);
}
А #
заполнители не будут отображаться, если туда не будет помещено число, отличное от нулей, а десятичная точка не отображается, если за ней что-то не идет.