I need a way to format numbers. I stored some numbers in my DB table, e.g. 12500
, and would like to print them in this format 12 500
(so there is a space every 3 digits). Is there an elegant way to do this?
问题:
回答1:
see: http://www.justskins.com/forums/format-number-with-comma-37369.html
there is no built in way to it ( unless you using Rails, ActiveSupport Does have methods to do this) but you can use a Regex like
formatted_n = n.to_s.reverse.gsub(/...(?=.)/,'\&,').reverse
回答2:
Activesupport uses this regexp (and no reverse reverse).
10000000.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1 ") #=> "10 000 000"
回答3:
Here's another method that is fairly clean and straightforward if you are dealing with integers:
number.to_s.reverse.scan(/\d{1,3}/).join(",").reverse
number #=> 12345678
.to_s #=> "12345678"
.reverse #=> "87654321"
.scan(/\d{1,3}/) #=> ["876","543","21"]
.join(",") #=> "876,543,21"
.reverse #=> "12,345,678"
Works great for integers. Of course, this particular example will separate the number by commas, but switching to spaces or any other separator is as simple as replacing the parameter in the join
method.
回答4:
The official document suggests three different ways:
1) Using lookbehind and lookahead (Requires oniguruma)
12500.to_s.gsub(/(?<=\d)(?=(?:\d{3})+\z)/, ' ')
# => "12 500"
2) Using only lookahead. Identical to steenslag's answer.
3) Using neither lookahead nor lookbehind
s = 12500.to_s
nil while s.sub!(/(.*\d)(\d{3})/, '\1 \2')
s # => "12 500"
回答5:
very simple:
number_with_delimiter(12500, delimiter: " ")
see: http://apidock.com/rails/ActionView/Helpers/NumberHelper/number_with_delimiter
回答6:
So, this is pretty crazy and hackish, but it gets the job done...
12500.to_s.split("").reverse.each_slice(3).map {|y| y.join("").reverse}.reverse.join(" ")
=> "12 500"
.to_s: convert to string
.split(""): split into separate digits
.reverse: reverse order
.each_slice(3): peel of each three digits (working from back end due to reverse)
.map {|y| y.join("").reverse}: map into an array for each three digits - join back together with no delimiter and reverse order back to original
.reverse: reverse order of mapped array
.join(" "): join mapped array back together with space delimiter
回答7:
Another way:
12500.to_s.reverse().split(//).inject() {|x,i| (x.gsub(/ /,"").length % 3 == 0 ) ? x + " " + i : x + i}.reverse()
You can always Open the Fixnum class and add this for convenience:
module FormatNums
def spaceify
self.to_s.reverse().split(//).inject() {|x,i| (x.gsub(/ /,"").length % 3 == 0 ) ? x + " " + i : x + i}.reverse()
end
end
class Fixnum
include FormatNums
end
12500.spaceify # => "12 500"
回答8:
All but one of the answers use n.to_s
. @MrMorphe's does not, but he creates an array to be join
ed. Here's a way that uses neither Fixnum#to_s nor Array#join.
def separate(n,c=' ')
m = n
str = ''
loop do
m,r = m.divmod(1000)
return str.insert(0,"#{r}") if m.zero?
str.insert(0,"#{c}#{"%03d" % r}")
end
end
separate(1) #=> "1"
separate(12) #=> "12"
separate(123) #=> "123"
separate(1234) #=> "1 234"
separate(12045) #=> "12 045"
separate(123456) #=> "123 456"
separate(1234000) #=> "1 234 000"
Hmmm. Is that column on the right tipping?
Another way that uses to_s
but not join
:
def separate(n, c=' ')
str = n.to_s
sz = str.size
(3...sz).step(3) { |i| str.insert(sz-i, c) }
str
end
回答9:
This is old but the fastest and most elegant way I could find to do this is:
def r_delim(s, e)
(a = e%1000) > 0 ? r_delim(s, e/1000) : return; s << a
end
r_delim([], 1234567).join(',')
I'll try and add benchmarks at some point.
回答10:
Another way:
Here "delimiter is ' '
(space), you can specify ','
for money conversion."
number.to_s.reverse.gsub(%r{([0-9]{3}(?=([0-9])))}, "\\1#{delimiter}").reverse
回答11:
I just stumbled on this thread while looking for a way to format a value as US currency. I took a slightly different approach to the regex solutions proposed:
amt = 1234567890.12
f_amt = format("$%.2f",amt)
i = f_amt.index(".")
while i > 4
f_amt[i-3]=","+f_amt[i-3]
i = f_amt.index(",")
end
f_amt
=> "$1,234,567,890.12"
This could be parameterized for formatting other currencies.
回答12:
I'm aware this is an old question but.
why not just use a substring substitution.
in pseudo code....
String numberAsString = convertNumberToString(123456);
int numLength = V.length;//determine length of string
String separatedWithSpaces = null;
for(int i=1; i<=numlength; i++){//loop over the number
separatedWithSpaces += numberAsString.getCharacterAtPosition(i);
if(i.mod(3)){//test to see if i when devided by 3 in an integer modulo,
separatedWithSpaces += " ";
}//end if
}//end loop
I know it isn't in any particular languange, but hopefully you get the idea.
David