Czy istnieje sztuczka polegająca na dodawaniu przecinków do dużych liczb?


201

Czy istnieje sposób na wydrukowanie na szynach numeru z przecinkami?

Na przykład, jeśli mam numer 54000000.34, mogę uruchomić <% = liczba.funkcja%>, która wyświetliłaby „54 000 000,34”

dzięki!

Odpowiedzi:


353

Chcesz number_with_delimitermetodę. Na przykład:

<%= number_with_delimiter(@number, :delimiter => ',') %>

Alternatywnie możesz użyć tej number_with_precisionmetody, aby upewnić się, że liczba jest zawsze wyświetlana z dokładnością do dwóch miejsc po przecinku:

<%= number_with_precision(@number, :precision => 2, :delimiter => ',') %>

5
@Mo Jest to metoda pomocnika widoku. Powinieneś być w stanie używać go z modułu poprzez włączenie go ActionView::Helpers::NumberHelperdo modułu.
John Topley,

9
Uważam, że domyślnie separator jest przecinkiem, więc w tym przypadku nie trzeba podawać tej opcji.
Deekor,

3
Powinieneś pozostawić wyłącznik wyłączony, aby bieżące ustawienia narodowe mogły zdecydować, którego użyć. Dzięki temu ustawienia narodowe, które używają kropek dla separatorów, są wyświetlane poprawnie, zamiast umieszczania tego, co uważają za kropkę dziesiętną między tysiącami. Zobacz odpowiedź coloradoblue poniżej.
Kyle Heironimus

1
Składnia Rails 4: <% = liczba_z_precyzyjnością (@numer, precyzja: 0, separator: ',')%>
Choylton B. Higginbottom

2
Uwaga: number_with_delimiterjest zbyt skomplikowany i bardzo powolny, z ogromną głębokością stosów połączeń. Służy i18ndo formatowania dowolnych liczb znanych ludzkości i cywilizacjom pozaziemskim (lub może po prostu wybrać cyfrę dziesiętną ,lub .dziesiętną, nawet jeśli podasz ją jako argument). Przydziela tysiące obiektów (więc wzorce wydajności są złożone i trudne do profilowania). Rozważ użycie wyrażeń regularnych, jeśli nie potrzebujesz obsługiwać różnych sposobów formatowania liczb w zależności od ustawień regionalnych.
kolen

133

Dla każdego, kto nie używa szyn:

number.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse

2
Miły. Twoja odpowiedź wydaje się być drobiazgowa (tylko ułamek sekundy na milion iteracji) szybsza niż przedstawione tutaj podejście :number.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse
user664833,

czy możesz wyjaśnić, co się tutaj dzieje? number.to_s.reverse.gsub (/ (\ d {3}) (? = \ d) /, '\\ 1,'). wstecz
Stephen Nguyen

7
Jasne, odwraca ciąg, następnie dodaje przecinek po dowolnej sekwencji 3 cyfr, po której następuje także kolejna cyfra, a następnie odwraca go z powrotem.
pguardiario

1
@renosis - Rozumiem, co masz na myśli, służy do formatowania waluty. Więc 2 miejsca po przecinku, a nie 7.
pguardiario

2
@pguardiario Do czego służy \ w \\ 1? nie \1wystarcza? Dzięki.
butterywombat

31

Bezpośrednim sposobem na to, z Railsami lub bez , jest:

require 'active_support/core_ext/numeric/conversions'

12345.to_s(:delimited)      # => "12,345"
12345.6789.to_s(:delimited) # => "12,345.6789"

Aby uzyskać więcej opcji, zobacz Aktywne rozszerzenia podstawowe wsparcia - Numeryczne - Formatowanie .


1
I dzięki temu włączeniu możesz również użyć ActiveSupport::NumberHelper.number_to_delimited. Ta odpowiedź zasługuje na dużo więcej pozytywnych opinii.
Ulysse BN


24

Jeśli chcesz dodać przecinki poza widokami i nie chcesz dołączać niektórych modułów, możesz użyć metody number_to_delimited (wersja szyn>> 4.02). Na przykład:

#inside anywhere
ActiveSupport::NumberHelper.number_to_delimited(1000000) # => "1,000,000"

19

Jeśli robisz to dużo, ale także FYI, ponieważ nie wynika to z powyższego, Rails ma rozsądne wartości domyślne dla tej number_with_delimitermetody.

#inside controller or view
number_with_delimiter(2444323.4)
#=> 2,444,323.30

#inside console
helper.number_with_delimiter(233423)
#=> 233,423

Nie musisz podawać wartości separatora, jeśli robisz to w najbardziej typowy sposób.


Ma to dodatkową zaletę korzystania z bieżących ustawień regionalnych. Jest to naprawdę ważne w aplikacjach międzynarodowych, ponieważ niektóre ustawienia narodowe używają przecinka dla dziesiętnego i kropki dla separatora tysięcy.
Kyle Heironimus

16

Lepszy sposób dla tych, którzy nie używają szyn, które obsługują dziesiętne:

parts = number.to_s.split('.')
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
parts.join('.')

Jeśli chcesz innego separatora, zmień ostatnie „,” w wyrażeniu regularnym.

W przypadku premii działa to wyrażenie regularne:

  • gsub zastępuje wszystko, co pasuje do wyrażenia regularnego, drugim parametrem przekazanym do gsub. W tym przypadku tak jest \\1. \\1staje się \1po ocenie, która pasuje do pierwszej grupy przechwytywania w wyrażeniu regularnym. To jest w tym wyrażeniu regularnym (\d).
  • (\d)(?=(\d\d\d)+)dopasowuje cyfrę, po której następuje 1 lub więcej grup 3 cyfr. Pierwszy zestaw parenów to nasza \1grupa przechwytywania, drugi byłby \2. Gdybyśmy to po prostu zostawili, otrzymalibyśmy: 123456.gsub!(/(\d)(?=(\d\d\d)+)/, "\\1,") #=> 1,2,3,456To dlatego, że 1234 mecze, 2345 meczów i 3456 meczów, więc wstawiamy przecinek po 1, 2 i 3.
  • Dodając (?! \ D), dopasowujemy wszystko, co nastąpi wcześniej, co nie poprzedza cyfry, więc (\d)(?=(\d\d\d)+(?!\d))oznacza dopasowanie cyfry, po której następują 3 cyfry, po których nie następuje cyfra. Powodem, dla którego to działa, jest to, że gsub będzie zastępował rzeczy pasujące do łańcucha. Gdybyśmy tylko zamienili pierwszy mecz, to dla liczby takiej jak 123456789 otrzymalibyśmy 123456,789. Ponieważ 123456 789 nadal pasuje do naszego wyrażenia regularnego, otrzymujemy 123 456 789.

Oto skąd mam kod: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper.rb#L298-L300

I tutaj dowiedziałem się o tym, co się dzieje w tym wyrażeniu regularnym: http://www.tutorialspoint.com/ruby/ruby_regular_expressions.htm


działa jak urok, szczególnie w płynnym szablonie {{ value | round | replace: "(\d)(?=(\d\d\d)+(?!\d))", "$1," | prepend: "$" }}
językowym

2

Inne rozwiązanie, które nie korzysta z Pomocników: formatuj z 2 miejscami po przecinku, a następnie zamień. przez ,

puts(("%.2f" % 2.5666).gsub('.',','))
>> 2,57

1
Sądzę, że pytanie dotyczyło przecinków w grupowaniu cyfr , a nie przecinków jako separatora dziesiętnego części / części ułamkowej, który osiąga twoja odpowiedź. (jak wyjaśnia ten link wiki, ze względu na długotrwałe zamieszanie, standardy internetowe zalecają teraz spacje tylko dla grupowania cyfr)
Beni Cherniavsky-Paskin

1

Możesz użyć metod z ActiveSupport

Na przykład:

ActiveSupport::NumberHelper::number_to_currency(10000.1234,{precision: 2,unit: ''})


1
  def add_commas(numstring)
    correct_idxs = (1..100).to_a.select{|n| n % 6 == 0}.map{|n| n - 1}
     numstring.reverse.chars.join(",").chars.select.with_index{|x, i| i.even? || correct_idxs.include?(i)}.join.reverse
  end

To była moja droga w rubinie

Edycja dodawania: Zasadniczo dodaje wszystkie przecinki między liczbami i wybiera tylko te, w których indeks + 1% 6

Doszedłem do wniosku, że przecinki do 100 są w porządku, ale jeśli chcesz super długiej liczby, po prostu zwiększ 100



0

Wykonaj sztuczkę zarówno dla separatora, jak i precyzji ( odwołanie API ).

ActiveSupport::NumberHelper.number_to_rounded(1234.532, delimiter: ',', precision: 1) 

(lub tylko z widoków number_to_rounded, nie ma potrzeby przyrostka)

HTH


-1

dla javascript

function numberWithDelimiter(value) {
    return (value+"").split("").reverse().join("").replace(/(\d{3})(?=\d)/g, '$1,').split("").reverse().join("")
}

:)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.