【问题标题】:What's the right way to represent phone numbers?表示电话号码的正确方法是什么?
【发布时间】:2011-03-29 19:55:03
【问题描述】:

我在我的一个应用程序中表示手机号码时遇到问题。

我想知道是否有一个 Integer 类可以让您存储以 0417254482 开头的数字。也许使用字符串更合适? 目前,当我尝试使用整数表示电话号码时,我似乎存储的是随机数而不是我打算存储的数字。

【问题讨论】:

  • @Raze2dust:在这种情况下不需要任何代码。
  • @Jon 我的意思是它显示一个随机数的部分。如果它显示的数字前导零被截断,但随机数是可以理解的?我需要查看代码来解决这个问题..
  • @Raze2dust:嗯,不是“随机的”——但将其存储在 double 中肯定会丢失数据。
  • 如果它前面有一个0,如果你在 PHP 中工作,请为地狱做好准备:P
  • 但是有一个“窍门”可以玩:总是在数字的字符表示之前添加一个“假”“1”数字,然后再将其转换为二进制,然后总是去掉第一个格式化回十进制后的值(可能“断言”它是“1”)的字符。这将允许您将大多数电话号码(包括大量前缀)存储为 64 位整数。

标签: java integer phone-number


【解决方案1】:

如果您想进行验证和规范化,您可能需要依赖一个能够为您正确完成这些工作的库。 https://github.com/googlei18n/libphonenumber 是最常见的选项之一。

【讨论】:

    【解决方案2】:

    虽然电话号码是命名数字,但它们通常不是数字(例如,前导零、国家/地区前缀 +XX、...)。

    所以在程序中正确表示电话号码有两种可能性:

    1. 使用String 保留输入的整数。
    2. 使用为电话号码功能提供额外支持的自定义数据类型

      public class PhoneNumber implements Comparable<PhoneNumber>{
      
          private String countryCode;
      
          private String areaCode;
      
          private String subscriberNumber;
      
          // Constructor(s)
      
          // Getter
      
          // HashCode + Equals
      
          // compareTo
      
          @Override
          public String toString(){
              return countrycode + " " + areaCode + " " + subscriberNumber;
          }
      }
      

    看看所有不同的conventions that are used internationally真的很有趣

    【讨论】:

    • 此外,它还取决于您的应用程序的复杂程度。普通应用程序只需要字符串表示,仅此而已,而用于保存地址和对其执行查询的复杂应用程序需要更复杂的处理。
    • 您可以采用电话号码必须包含国家/地区前缀的约定,在这种情况下没有前导零。
    【解决方案3】:

    您应该使用字符串或更专业的数据结构。

    主要原因是您可以对电话号码执行的操作是字典式的,而不是算术式的。 例如您可以说法国的电话号码以 +33 开头,但您不能假设它们在数字范围内。

    我认为这些其他论点无效

    • 电话号码可以包括*#。这些符号可以在电话线上传输,但它们不是电话号码本身的一部分,我认为它超出了范围。
    • 电话号码可以以前导零开头。本地电话号码可以,但它们首先是有限的代表。国际电话号码以国家代码开头,并且没有一个前导零。因此,国际电话号码没有前导零。
    • 电话号码以 + 开头。一个数字可以完美地代表这一点,只要是积极的。同样以+开头的只是E164号码的一种表示,这样就可以和本地号码区分开来。如果您只操作 E164 号码,他们真的不必这样做。
    • 电话号码可以包含空格或括号。这是荒谬的,因为它只是数字的文本表示。您不应该存储它,因为人们可能有不同的个人偏好来分隔数字组(.- 等)。

    【讨论】:

    • 只有当您可以自信地将输入的号码标准化为国际形式时,有关本地电话号码的论点才成立。如果您要使用自动拨号器,这可能是一种约束,但如果您要在某处显示号码,最好保留原始格式,包括可能不明确的本地形式。
    【解决方案4】:

    使用String。除此之外,如果您使用整数,您将无法存储前导零。你绝对不应该使用int(太小)floatdouble(数据丢失风险太大 - 见下文); longBigInteger 可能是合适的(除了前导零问题),但坦率地说,我会选择 String。这样,您可以存储用户输入的任何破折号或空格,以便更容易记住数字,如果您愿意的话。

    就上面提到的floatdouble 的“数据丢失”而言-float 绝对没有足够的精度; double 可以工作,如果你很高兴你永远不需要超过 16 位数字(比 long 少几个),但你需要非常非常小心将值从double 转换回string 的任何位置,您都得到了准确的值。许多格式转换将为您提供一个近似值,该近似值可能精确到 10 位有效数字 - 但您需要一个精确的整数。基本上,对电话号码使用浮点是一个根本性的坏主意。如果您必须使用固定宽度的数字类型,请使用long,但最好完全避免使用它。

    【讨论】:

    • 请原谅我的无知,但是任何电话号码实际上都以前导零开头吗?
    • @WesleyMurch:所有英国电话号码都以 0 开头。例如,雷丁的区号是 ​​0118。
    • @ColeJohnson 错误地在 C# 代码中编辑不是他的错。有人关闭了这个问题的the C# version,说它是这个问题的副本。恕我直言,区分编程语言非常重要。
    • 有趣的是,我工作的编码标准有以下一行:“电话号码和邮政编码是数值。”并要求我们在数据库级别为它们使用数字。这个想法是,如果它是一个字符串,你可以获得各种奇怪的格式(例如,一个人输入 (555) 123-4567,另一个人输入 555-123-4567),而如果它是一个数字,你可以自己格式化。虽然公平地说,我们不处理国际事务,所以这对我们来说可能更有意义。
    • @WayneM:这对我来说听起来是个坏主意,如果你需要处理其他国家/地区,几乎肯定会咬你...
    【解决方案5】:

    每个数字的左右两边都有无穷多个零,

    要表示它,您应该使用字符串格式

    class PhoneNumber implements Comparable<PhoneNumber> {
    
        private Long number;
    
        public PhoneNumber(Long number) {
            this.number = number;
        }
    
        public Long getNumber() {
            return this.number;
        }
    
        public boolean equals(Object object) {
    
            if (getNumber() == null && object == null) {
                return true; //or false its depend 
            }
    
            return getNumber().equals(object);
        }
    
        public int compareTo(PhoneNumber that) {
    
                if(that == null) {
                 return -1;
                }
    
            Long thisNumber = getNumber();
                Long thatNumber = that.getNumber();
    
            if (thisNumber == null && thatNumber == null) {
                return 0; //or -1
            }
    
            if (thisNumber == null && thatNumber != null) {
                return -1;
            }
    
            return thisNumber.compareTo(thatNumber);
    
        }
    
        @Override
        public String toString() {
            return String.format("%010d", getNumber());
        }
    }
    

    使用的 %010d 均值 %[argument_index$][flags][width][.precision]conversion

    标志 0 - 填充零 10 - 填充零的数量 d - 十进制整数

    接口 Comparable 的实现使您可以对 List 进行排序。

    List<PhoneNumber> phoneNumbers = new ArrayList();
     phoneNumbers.add(new PhoneNumber (123L);
     phoneNumbers.add(new PhoneNumber (123777L);
     phoneNumbers.add(new PhoneNumber (125L);
     phoneNumbers.add(new PhoneNumber (124L);
     phoneNumbers.add(new PhoneNumber (126L);
    
    Collections.sort(phoneNumbers);
    
      for(PhoneNumber phoneNumber : phoneNumbers) {
       System.Console.Out.WriteLine(phoneNumber);
      }
    

    输出是

     0000000000 
     0000000123
     0000000124
     0000000125
     0000000126
     0000123777
    

    Comparable String Formatter

    【讨论】:

    • 代码有一些错误(缺少分号)但除此之外它是解决它的完美方法。
    • -1 推荐使用数字。抱歉 @Vash 将您的 9,100 代表更改为 9,098。另外,为什么使用class 而不是struct?如果结构包含数据,比如这个,使用struct。如果它包含“对象”并做一些事情(如Stream),则使用class。如果将int 定义为class Int32 是否有意义?
    • @Cole Johnson,也可以,开发者选择类型。在我看来,long 更好,因为您能够以不同的方式格式化字符串。有时会要求这样做。所以它比字符串更全球化。它的工作速度也更快,更轻。那么您使用 String 背后的逻辑是什么?关于第二个问题。您对类和结构的解释不清楚。我之所以选择课程,是因为我不需要每次使用电话时都需要一份电话副本。我想使用引用类型的力量。所以如果我操纵它的内部。该类并非设计为不可变的。
    • @Cole Johnson,您对类与结构的定义是恕我直言。该决定应基于您将如何使用数据。我绝对不同意这样的观点,即结构的选择应该基于包含的数据。
    • 像这样填充到固定长度可以让您支持世界电话号码的一小部分。也许在某些国家/地区它是 a) 必要的,因为使用了前导零,b) 足够了,因为所有数字的长度都相同,但这绝对不是“解决它的完美方法”。
    【解决方案6】:

    使用 String 类型的私有字段创建您自己的 PhoneNumber 类来表示它。

    public class PhoneNumber {
       private String number;
       public PhoneNumber(String number) {
          //check validity of number
          this.number = number;
       }
       //getter, comparator, etc...
    }
    

    如果所有电话号码的长度相同,您也可以用 long 或 BigInteger 表示号码,但请注意前导零。

    电话号码并不是真正的整数(或字符串)。它是其他应该有自己的类的东西。

    编辑: 还有一件事:我不会为这个类实现 setter,因为电话号码对象最好是不可变的

    【讨论】:

    • 添加 compareTo 和 equals 方法将使排序按照提问者在这种情况下的要求工作。
    • @matto:你说得对。他应该实现 compareTo 和 equals。谢谢。
    • 如果您只是将数字本身存储在原子字符串中,则无需将其包装到新类中,因为所有方法(如 hashCode,...)本质上都会委托给 String 提供的实现.
    【解决方案7】:

    想一想:电话号码真的是数字吗?用电话号码添加(或进行另一个算术运算)是否有意义?电话号码是代码,它们通常用数字表示,但这只是一种约定,也许在另一个国家也使用字母(我刚刚意识到,国际电话号码呢?他们有一个+ 在开始。 您必须考虑要表示的事物的性质,然后找到最合适的表示。

    【讨论】:

    • +1 我猜你可以用 00 替换 +,所以丹麦(我在哪里)是 0045 XXXX XXXX。
    • 是的。这是真的 + 可以用来代替 00,反之亦然。
    • 我没有对 ID 进行任何算术运算,但我将它们存储了很长时间。
    • @rds:因为对于每个新记录,ID 通常递增 1,这是一种算术运算。你自己可能不会这样做,但它确实会发生。
    • @rds 使用数字 ID 有一个很好的论据,因为人们最终会将它们用于排序之类的事情,即使它们没有任何意义。如果工具更好地支持它,我们最好使用 GUID 样式的随机标识符,以紧凑的二进制形式存储。
    【解决方案8】:

    您应该使用字符串来支持带有前导零的数字。您提供的代码是:

    Order order1 = new PickUpOrder(orderTime, 0473519954); 
    //The pickup order requires an orderTime (String) and a contact number(Int). Heres    
    //the constructor for PickUpOrder. 
    
    public PickUpOrder(Date orderTime, String number) 
    { 
        discount = .2; 
        phoneNumber = number; 
        super.setOrderTime(orderTime); 
        //Test print 
        System.out.println(phoneNumber) 
        //reads int as 74049273 instead of 0473519954 
    }
    

    在构造函数中,数字是字符串,但是当您调用构造函数时,您使用 int 作为电话号码。我认为java中一定存在编译错误。这和你编译的代码一样吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 1970-01-01
      相关资源
      最近更新 更多