What's the right way to represent phone numbers?
Asked Answered
F

9

63

I'm having trouble representing a mobile number in one of my applications.

I was wondering if there is an Integer class that will allow you to store such a number starting with 0417254482. Perhaps using a string be a more appropriate? At present when I'm trying to use represent a phone number with ints, doubles longs I seem to store random numbers and not the numbers I meant to store.

Fiacre answered 14/8, 2010 at 11:58 Comment(6)
@Raze2dust: There's no need for any code in this case.Skylab
@Jon I meant for the part that it displays a random number.. it is understandable if it is displaying the number with leading zeros truncated, but a random number? I'd need to see code to solve that..Waaf
@Raze2dust: Well, not "random" - but storing it in a double could certainly lose data.Skylab
If it has a 0 before it, prepare yourself for hell if you're working in PHP :PAbelabelard
All fixed-length "number" types store leading zeros. But since the leading zeros are rarely meaningful, most number formatting routines remove them. But note that the number of leading zeros in a fixed-length number type will always be the number required to "pad out" a given number value to the maximum number of digits the number type can possibly represent -- there's no way to "tell it" to store one leading zero or two or none. For that you need either a character representation or a variable-length decimal representation.Jura
But there is a "trick" that can be played: Always add a "bogus" "1" digit to the front of the number's character representation before converting it to binary, and then always strip the first character off the value (and maybe "assert" that it's "1") after formatting back to decimal. This would allow you to store most phone numbers (including a substantial prefix) as 64-bit integers.Jura
S
144

Use String. Aside from anything else, you won't be able to store leading zeroes if you use integers. You definitely shouldn't use int (too small) float or double (too much risk of data loss - see below); long or BigInteger could be appropriate (aside from the leading zeroes problem), but frankly I'd go with String. That way you can also store whatever dashes or spaces the user has entered to make it easier to remember the number, if you want to.

In terms of the "data loss" mentioned above for float and double - float definitely doesn't have enough precision; double could work if you're happy that you'll never need more than 16 digits (a couple fewer than you get with long) but you would need to be very, very careful that anywhere you convert the value back from double to string, you got the exact value. Many formatting conversions will give you an approximation which may be accurate to, say, 10 significant digits - but you'd want an exact integer. Basically, using floating point for phone numbers is a fundamentally bad idea. If you have to use a fixed-width numeric type, use a long, but ideally, avoid it entirely.

Skylab answered 14/8, 2010 at 12:1 Comment(9)
Forgive my ignorance, but do any phone numbers actually start with a leading zero?Untwine
@WesleyMurch: All UK phone numbers start with a 0. For example, the area code for Reading is 0118.Skylab
It's not @ColeJohnson's fault that he incorrectly edited in C# code. Someone closed the C# version of this question, saying it's a duplicate of this question. Distinguishing between programming languages is rather important, IMHO.Meridithmeriel
Funnily enough, my job's coding standards has the following line: "Phone numbers and zip codes are numeric values." and requires us to use numeric for them at the database level. The idea is that if it's a string, you can get all kinds of wonky formatting (e.g. one person enters (555) 123-4567, another enters 555-123-4567), while if it's a numeric you can format it yourself. Although to be fair, we do not handle international things so it maybe makes more sense for us.Hegemony
@WayneM: That sounds like a bad idea to me, and would almost certainly bite you if you ever needed to handle other countries...Skylab
Let us continue this discussion in chat.Laborsaving
@WesleyMurch Also most Japanese phone numbers start with 0. 090 or 080 or 03Kendre
Definitely better would be to introduce some ValueObject that represent PhoneNumber. The implementation might be than trivial like presented here but at least will be encapsulated with VO plus might be extended or even change if it will be needed.Troytroyer
When I need to account for international numbers, I use BINARY at the SQL side and a custom type to destructure it at the client side. Four first bytes are used for the country code and flags (such as LEADING_ZERO), 16 next accounts for the actual number. When there's no such requirement and we do only local numbering, INT(9) UNSIGNED is sufficient on its own, since we don't have leading zeros or any similar weirdness, all numbers are required to have exactly 9 digits.Rienzi
A
48

Think about this: Is a phone number really a number? Does it make sense adding (or make another arithmetic operation) with phone numbers? Phone numbers are codes, they're usually represented with numbers, but that's just a convention and, maybe, in another country the use letters too (I've just realized, what about international phone numbers? they have a + at the beginning. You have to think about the nature of the things you want to represent, and then, find the most suitable representation.

Altruism answered 14/8, 2010 at 12:16 Comment(6)
+1 I guess you can replace + by 00 so Denmark (where I am) is 0045 XXXX XXXX.Zebec
Yes. That is true + can be used instead of 00 and vice versa.Corney
I'm not doing any arithmetic operations on IDs, and yet I store them as long.Spielman
@rds: Because IDs are normally incremented by 1 for every new record, which is an arithmetic operation. You may not be doing it yourself, but it does happen.Parlando
@Spielman There's a good argument to be made for not using numeric IDs, because people than end up using them for things like sorting, even though they have no meaning. If the tools supported it better, we would be better off using GUID-style random identifiers, stored in a compact binary form.Meister
Best answer in my opinion, use integral numbers (int/long) or floating point numbers only when you actually want to calculate with them directly. Even an ID number that is protected by a check digit (ie creditcard/bank account numbers) are not longs/etc. because you may want to calculate with the individual digits, but never with the number as a whole.Subtenant
M
7

If you want to do validation and normalization you probably want to rely on a library that does it properly for you. https://github.com/googlei18n/libphonenumber is one of the most common options.

Marvamarve answered 5/7, 2018 at 12:42 Comment(0)
T
6

Although phone numbers are named numbers, they are normally not numbers (e.g. leading zeros, country prefix +XX, ...).

So there are two possibilities to represent a phone number correctly inside a program:

  1. Using String to keep the whole number like entered.
  2. Using a custom data type that offers additional support for phone number features

    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;
        }
    }
    

It's really interesting to look at all the different conventions that are used internationally

Tradelast answered 14/8, 2010 at 17:38 Comment(2)
Additionally it also depends on how complex your applications gets. A normal application would only need String representation and nothing more whereas complex applications for keeping addresses and performing queries onto them would need more sophisticated handling.Tradelast
You could take the convention that a phone number must include the country prefix, in which case there is no leading zero.Spielman
M
5

Create your own PhoneNumber class with a private field of type String to represent it.

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

You could also represnt the number with long or BigInteger if all phone numbers have the same length, but be careful with leading zeros.

A phone number is not really an integer (or a string). It is something else which shuld have a class of its own.

EDIT: one more thing: I wouldn't implement a setter for this class because a phone number object would better be immutable

Marysa answered 14/8, 2010 at 12:10 Comment(3)
Adding a compareTo and equals method would make the sorting work as the questioner asked in this case.Flowering
@matto: Your'e right. He should implement compareTo and equals. Thanks.Marysa
if you're just storing the number itself in an atomic String there's no need to wrap that into the new class since all the methods like hashCode, ... would essentially delegate to the implementations provided by String.Tradelast
S
2

You should use a string or a more specialized data structure.

The main reason is that the operations that you can do on phone numbers are lexicographic, and not arithmetic. e.g. You can say that phone numbers for France start with +33, but you cannot assume they are in a numerical range.

These other arguments are not valid in my opinion

  • a phone number can include * or #. This symbols can be transported on phone lines, but they are not part of the phone number itself, and I consider it's out of scope.
  • a phone number can start with leading zeros. Local phone numbers can, but they are a limited representation in the first place. International phone numbers start with a country code, and none of them has a leading zero. Hence no international phone number has leading zeros.
  • a phone number starts with +. A number can perfectly represent this, by simply being positive. Also starting with + is just a representation of E164 numbers, so that they can be distinguished from local numbers. They really don't have to, if you only manipulate E164 numbers.
  • a phone number can contain spaces or parentheses. This is absurd, because it's just textual representation of the number. You shouldn't store this as people can have different personal preferences to separate groups of digits (., -, , etc.).
Spielman answered 4/12, 2015 at 14:59 Comment(1)
The argument about local phone numbers is only true if you can confidently normalise the number entered into international form. That might make sense as a constraint if you're going to use an automatic dialler, but if you're going to display the number somewhere, you're much better off retaining the original formatting, including potentially ambiguous local forms.Meister
J
0

Every number have infinity amount of zeros on the left and right side,

To represent it you should use a string formating

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());
    }
}

Used %010d mean %[argument_index$][flags][width][.precision]conversion

flag 0 - padding zeros 10 - amount of padding zeros d - decimal integer

The implementation of interface Comparable give you the posibility to sort 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);
  }

The output is

 0000000000 
 0000000123
 0000000124
 0000000125
 0000000126
 0000123777

Comparable String Formatter

Jag answered 14/8, 2010 at 12:2 Comment(5)
The code has a few mistakes (missing semi colons) but apart from that it's the perfect way to solve it.Flowering
-1 Recommending usage of a number. Sorry @Vash for changing your 9,100 rep to 9,098. Also, why use a class instead of struct? If the structure encompasses data, like this one, use struct. If it encompasses "objects" and does things (like Stream), then use class. Would it make sense if int was defined as class Int32?Abelabelard
@Cole Johnson, It is up too, developer to choose the type. For my point of view, long is better as you are able to format the string in differ way. That sometimes is requested. SO it is more globalized than string. It also work faster and is lighter. So what is your logic behind String usage ? Regarding the second question. Your interpretation of class and structures is unclear. I have choose class because i do not need a copy of phone each time it is used. I want to use the power of reference type. So if I manipulate the interiors of it. The class is not designed to be immutable.Corney
@Cole Johnson, your definition of class vs. struct is fault IMHO. The decision should be based on how you will use the data. I definitely disagree with opinion, that selection of structure should be based on the encompasses data.Corney
Padding to a fixed length like this gives you support for a ridiculously small subset of the world's phone numbers. Maybe there is some country where it's a) necessary because leading zeroes are used, and b) sufficient because all numbers are the same length, but it's definitely not "the perfect way to solve it".Meister
W
0

You should use string to support numbers with leading zeros. The code you provided was:

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 
}

In the constructor, the number is string but when you call the constructor you used an int for phone number. There must have been a compile error here in java I think. Is this the same code you compiled?

Waaf answered 14/8, 2010 at 12:13 Comment(0)
F
-1

I would suggest not use primitive data type.

Reason: Primitives cannot accept special characters such as +,-,(, and, ). If you accept phone numbers in this format +1(xxx)-xxx-xxxx.

Flotage answered 27/10, 2022 at 21:45 Comment(1)
How do you define that "primitive data type"? Which other would you use?Soviet

© 2022 - 2025 — McMap. All rights reserved.