【问题标题】:"Intelligent" cast of double to two differently formatted strings?双到两个不同格式的字符串的“智能”转换?
【发布时间】:2009-10-28 08:20:57
【问题描述】:

我正在使用的数据库有一个限制,它可以存储的唯一(数字)数据类型double。我想要做的是选择某一行的数字并将其放入 HTTP 请求中。问题在于我不知道这个数字是否应该有小数。

例如,如果 double 是一个 ID,我就不能有任何格式,因为获取 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

解决这个问题的方法是将其转换为长格式。忽略溢出长的问题,它解决了科学记数法和(显然)尾随小数。这可能是一个可接受的解决方案,但如果代码不假定它是我们正在处理的 ID,那就太好了。例如,如果我要查询一个显示地图的站点,并且数字是坐标,小数点非常重要,该怎么办?那么将不再接受转换为 long。

简而言之;

  • 如果双精度数没有小数,请勿添加尾随小数。
  • 如果有小数,请全部保留。
  • 大小写都不应该有科学记数法或千位分隔符。

此解决方案将同时移植到 C# 和 Java,因此我接受两种语言的答案。 (哦,我不知道如何称呼这个问题,如果你有更好的东西,请随时重命名。)

【问题讨论】:

    标签: c# java string format format-string


    【解决方案1】:

    为了补充 gustafc 的答案(他比我快 1 分钟),这里是 C# 的相关代码行:

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

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

    【讨论】:

      【解决方案2】:

      既然如果它是整数值(无论它表示一个 ID 还是一个坐标),那么格式化不带尾随零的值是安全的,为什么不把你在项目符号中描述的逻辑编成代码呢?例如(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")
      }
      

      【讨论】:

      • 日期不是大写的 D 吗?
      • 在 .NET、D 或 d 中,应用于数值时,表示“带有可选负号的整数位”。请参阅msdn.microsoft.com/en-us/library/dwhawy9k.aspx 了解更多信息。当应用于 DateTime 值时,它确实意味着不同的东西,但这不会影响你。当然,Java 可能会使用不同的东西;抱歉,对 Java 不够熟悉。
      • 是的,我认为它可以区分数字和日期时间值。但是在运行它时,我遇到了格式字符串异常。也许又犯了一个错误。
      【解决方案3】:

      将数字封装在自定义类型中怎么样?

      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- 的答案以获得比上述算法更好的算法。

      【讨论】:

      • 虽然自定义类型是个好主意,但格式化发生在一个非常小的模块中......双输入,字符串输出,界面不会有任何改变。因此,自定义类型只会在该函数中使用一小段时间。虽然它很好地包装了逻辑,但我认为代码库在一段时间内没有另一个类会更清晰。
      【解决方案4】:

      检查是否 num == round(num)

      【讨论】:

      • 解决方案的一部分,但这是检查小数的好方法。
      【解决方案5】:

      在 Java 中,您可以使用 DecimalFormat 执行此操作。

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

      # 占位符不会显示,除非数字不是零,否则小数点不会显示,除非它后面有东西。

      【讨论】:

      • #s 的数量有什么特殊原因吗?您不知道可以打印到字符串的最大小数位数吗?还不如一起去。
      • 添加很多就行了。无论如何,双精度都没有无限精度(你也不需要它),所以大约 16 个十进制数字应该足以满足所有意图和目的。但是,如果您喜欢它们,请随时添加更多内容。 :)
      【解决方案6】:

      这是我自己的结论:

      • Check if the double has decimals.
      • Depending on that, format the string accordingly.
      • 然后是一些重要的事情;如果不指定不变的区域性,小数部分中的逗号可能是“,”而不是“。” 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);
            }
        }
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-30
        • 2019-07-22
        • 2013-09-23
        • 2020-01-16
        • 2023-03-03
        • 1970-01-01
        相关资源
        最近更新 更多