Ruby .to_i не возвращает целое число, как ожидалось - PullRequest
0 голосов
/ 25 марта 2019

Моя команда ruby:

"980,323,344.00".to_i

Почему возвращается 980 вместо 980323344?

Ответы [ 3 ]

6 голосов
/ 25 марта 2019

Вы можете достичь этого, выполнив следующее:

"980,323,344.00".delete(',').to_i

Причина, по которой ваш вызов метода to_i не возвращается должным образом, объяснена здесь , и, к примеру, метод:

Возвращает результат интерпретации начальных символов в str как целочисленную базовую базу (от 2 до 36). Посторонние символы после окончания действительного числа игнорируются.

В вашем случае посторонние символы - это запятая, оканчивающаяся на 980, поэтому вы видите, что 980 возвращается

3 голосов
/ 25 марта 2019

При вызове ruby ​​to_i строка будет обрезаться от начала строки, где это возможно.

number_string = '980,323,344.00'
number_string.delete(',').to_i
#=> 980323344

"123abc".to_i
#=> 123

Если вы хотите добавить подчеркивания, чтобы сделать более длинное число более читабельным, их можно использовать там, где обычные запятые должны быть в письменных числах.

"980_323_344.00".to_i
#=> 980323344
2 голосов
/ 26 марта 2019

Документация для to_i может немного вводить в заблуждение:

Возвращает результат интерпретации начальных символов в str как целочисленную базу base (между 2 и 36)

«интерпретация» не означает, что она пытается проанализировать различные числовые форматы (как Date.parse для датыформаты).Это означает, что он ищет действительный целочисленный литерал в Ruby (в данной базе).Например:

 1234.            #=> 1234
'1234'.to_i       #=> 1234

 1_234.           #=> 1234
'1_234'.to_i.     #=> 1234

 0d1234           #=> 1234
'0d1234'.to_i     #=> 1234

 0x04D2           #=> 1234
'0x04D2'.to_i(16) #=> 1234

Ваш ввод в целом, однако, не является допустимым целочисленным литералом: (Руби не нравится ,)

980,323,344.00
# SyntaxError (syntax error, unexpected ',', expecting end-of-input)
# 980,323,344.00
#    ^

Но это начинается с действительного целочисленного литерала.И вот тут вступает в игру второе предложение:

Посторонние символы после конца действительного числа игнорируются.

Таким образом, результат равен 980 -начальные символы, которые образуют действительное целое число, преобразуемое в целое число.


Если ваши строки всегда имеют этот формат, вы можете просто delete запятые и ввести результат через to_i, который будет игнорировать конечный .00:

'980,323,344.00'.delete(',')      #=> "980323344.00"
'980,323,344.00'.delete(',').to_i #=> 980323344

В противном случае вы можете использовать регулярное выражение для проверки его формата перед его преобразованием:

input = '980,323,344.00'
number = case input
         when /\A\d{1,3}(,\d{3})*\.00\z/
           input.delete(',').to_i
         when /other format/
           # other conversion
         end

И если вы имеете дело сденежные значения, вам следует рассмотреть возможность использования гема money и его монетизации для анализа форматированных значений:

 amount = Monetize.parse('980,323,344.00')
 #=> #<Money fractional:98032334400 currency:USD>

 amount.format
 #=> "$980.323.344,00"

Обратите внимание, что для format требуется i18n, поэтому приведенный выше пример может потребовать некоторой настройки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...