170 / 91 / 71
Регистрация: 10.05.2014
Сообщений: 432
1
.NET 3.x

Число прописью перевести в число

11.04.2018, 13:43. Показов 8033. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго всем времени суток!

Столкнулся с проблемой, нужно строку, к примеру "Одна тысяча восемьсот девяносто рублей 00 коп" преобразовать в число "1890,00". С учетом того, что алгоритм сможет преобразовывать даже такие строки "Два миллиарда восемьдесят миллионов четыреста двадцать две тысячи сто девяносто два" (2 080 422 192) в свои числовые значения.

Была мысль реализовать чисел от нуля до триллиона, а в цикле считывать по порядку в словарь (string, int) , заполняя значение int переменной счетчика. Но как представлю сколько это А) писанины Б) памяти займет словарь на больших числах, что аж в дрожь бросает...

Если есть у кого-то идеи иной реализации, или кто-то уже сталкивался с подобным, подкиньте, пожалуйста, здравых мыслей в комментариях!

Заранее спасибо!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.04.2018, 13:43
Ответы с готовыми решениями:

Перевести число в число прописью
Я никак не пойму как делать. Вроде задание простое. Задача на С#. Программа принимает от...

Число прописью
написать программу, которая после введенного с клавиатуры числа(диапозон от 1 до 999),...

Вывести число прописью
Есть программа. В эдит в вожу: текстом задаю число от 0 до 999, после чего по нажатию на кнопку...

Вывести число прописью
Помогите разработать консольное приложение, с помощью которого целочисленное значение, вводимое с...

9
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,268
11.04.2018, 15:10 2
Zodt, я бы на вашем месте поигрался со словами и использовал бы условные конструкции if и окончания слов и переводил бы слова миллиард, миллион и т.п. в числа, в конце складывал бы их)
1
170 / 91 / 71
Регистрация: 10.05.2014
Сообщений: 432
12.04.2018, 11:21  [ТС] 3
Решил, все таки добивать в лоб. И опять проблема - числа менее тысячи хорошо переводятся, даже копейки переводит в десятичные числа, но вот как только в пропись добавляется слово тысяча и другие большие обозначения, начинается треш, угар и садомия... Я конечно, более чем уверен, что никто не захочет ковыряться в этом куске кода, но все же если кто-то решится на сей подвиг и найдет ошибку - помогите в её решении! Буду благодарен!


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
        
string[][] numbers =
{
            new string[3] {"ноль", "нуль", "0"},
            new string[5] {"один", "одна", "одну", "одно", "1"},
            new string[3] {"два", "две", "2"},
            new string[2] {"три", "3"},
            new string[2] {"четыре", "4"},
            new string[2] {"пять", "5"},
            new string[2] {"шесть", "6"},
            new string[2] {"семь", "7"},
            new string[2] {"восемь", "8"},
            new string[2] {"девять", "9"},
            new string[2] {"десять", "10"},
            new string[2] {"одиннадцать", "11"},
            new string[2] {"двенадцать", "12"},
            new string[2] {"тринадцать", "13"},
            new string[2] {"четырнадцать", "14"},
            new string[2] {"пятнадцать", "15"},
            new string[2] {"шестнадцать", "16"},
            new string[2] {"семнадцать", "17"},
            new string[2] {"восемьдесять", "18"},
            new string[2] {"девятнадцать", "19"},
            new string[2] {"двадцать", "20"},
            new string[2] {"тридцать", "30"},
            new string[2] {"сорок", "40"},
            new string[2] {"пятьдесят", "50"},
            new string[2] {"шестьдесят", "60"},
            new string[2] {"семьдесят", "70"},
            new string[2] {"восемьдесят", "80"},
            new string[2] {"девяносто", "90"},
            new string[2] {"сто", "100"},
            new string[2] {"двесте", "200"},
            new string[2] {"триста", "300"},
            new string[2] {"четыреста", "400"},
            new string[2] {"пятьсот", "500"},
            new string[2] {"шестьсот", "600"},
            new string[2] {"семьсот", "700"},
            new string[2] {"восемьсот", "800"},
            new string[2] {"девятьсот", "900"},
            new string[4] {"тысяч", "тысячи", "тысяча", "1000" },
            new string[4] {"миллиона", "миллионов", "миллион", "1000000"},
            new string[4] {"миллиарда", "миллиард", "миллиардов", "1000000000"},
            new string[4] {"триллион", "триллиона", "триллионов", "1000000000000"},
            new string[4] {"триллиард", "триллиарда", "триллиардов", "1000000000000000"},
            new string[4] {"квадриллион", "квадриллиона", "квадриллионов", "1000000000000000000" },
            new string[4] {"квинтиллион", "квинтиллиона", "квинтиллионов", "1000000000000000000000" },
            new string[4] {"секстиллион", "секстиллиона", "секстиллионов", "1000000000000000000000000" },
            new string[4] {"септиллион", "септиллиона", "септиллионов", "1000000000000000000000000000" },
            new string[4] {"октиллион", "октиллиона", "октиллионов", "1000000000000000000000000000000" },
            new string[4] {"нониллион", "нониллиона", "нониллионов", "1000000000000000000000000000000000" },
            new string[4] {"дециллион", "дециллиона", "дециллионов", "1000000000000000000000000000000000000" },
            new string[4] {"ундециллион", "ундециллиона", "ундециллионов", "1000000000000000000000000000000000000" }
        };
 
        /// <summary>
        /// Преобразователь чисел прописью в число цифрами.
        ///     Пример:
        ///     "17 триллиардов 8 триллионов Два миллиарда восемьдесят миллионов четыреста двадцать две тысячи сто девяносто два руб., 97 коп."
        /// </summary>
        /// <param name="text">Число прописью</param>
        /// <returns>
        /// Число цифрами
        ///     Пример:
        ///     17 008 002 080 422 192,97 (пробелы добавлены для простоты чтения итогового числа, на выходе их нет!)
        /// </returns>
        public decimal RecipeToNum(string text)
        {
            Regex reg = new Regex(@"[,.\/\\\(\)\-\+\=\*\&\?\^\%\$\#;'`~@\[\{\]\}\!\№\:]");
            text = reg.Replace(text, "");
            string[] words = text.Split();                          //массив заданных чисел прописью
            decimal[] num = new decimal[words.Length];              //массив, в который преобразуются числа прописью в числа чифрами
            bool flag = false;                                      //небольшие костыли =)
            decimal numeric = 0;                                    //итоговое число
 
 
            string tmp = "", tmp1 = "", tmp2 = "";                  //ненужные переменные для видимости в локальных переменных их значений
            int trep = 0; decimal temp = 0;
 
            for (int w = 0; w < words.Length; w++)                  //прогон по массиву заданных чисел прописью
            {
                if (words[w] == "рубль" ||                          //проверка на значение элемента массива words равному "руб"
                    words[w] == "рублей" ||
                    words[w] == "рубля" ||
                    words[w] == "руб")
                {
                    for (int d = trep == 0 ? 0 : w - trep; d < w; d++)  //если trep == 0, то это значит, что вхождения еще не было 
                    {                                                   //и начинается сложение с нулевого элемента массива, 
                        numeric += num[d];                              //иначе d равно разности w с предыдущим вхождением (когда words[w] == "тысяча", "руб", "коп" или что-то подобное)
                    }                                                   //в данном случае words[w] == "тысяча" или более бОльшим значениям, поэтому умножения нет (см. дальше)
 
                    trep = w;                                           //задается индекс вхождения, с которого в дальнейшем будет производиться сумма
                    temp = 0;                                           //обнуление темпа... ну так, на всякий случай =)
                    continue;
                }
                else
                if (words[w] == "копейка" ||                        //проверка на значение элемента массива words равному "коп"
                    words[w] == "копейки" ||
                    words[w] == "копеек" ||
                    words[w] == "коп")
                {
                    for (int d = trep == 0 ? 0 : w - trep; d < w; d++)  //если trep == 0, то это значит, что вхождения еще не было 
                    {                                                   //и начинается сложение с нулевого элемента массива, 
                        temp += num[d];                                 //иначе d равно разности w с предыдущим вхождением (когда words[w] == "тысяча", "руб", "коп" или что-то подобное)
                    }                                                   //в данном случае words[w] == "тысяча" или более бОльшим значениям, поэтому умножения нет (см. дальше)
 
                    numeric += temp == 0 ? 0 : temp / 100;              //сложение всех элементов стоящих между "руб" и "коп" с проверкой на равенство нулю
                    trep = w;                                           //задается индекс вхождения, с которого в дальнейшем будет производиться сумма
                    temp = 0;                                           //очередное обнуление темпа... опять же, на всякий случай =) 
                }
                else if (decimal.TryParse(words[w], out num[w]))        //проверка задано ли числом данный элемент массива
                {
                    continue;
                }
                else
                {
                    for (int i = 0; i < numbers.Length; i++)            //прогон по зубчатому массиву из массивов чисел прописью
                    {                                                   
                        if (flag)                                       //флаг для окончания прогона по массиву, когда значения уже получены
                        {                                               
                            flag = false;
                            break;
                        }
                        for (int j = 0; j < numbers[i].Length - 1; j++)         //прогон по элементам внутреннего массива с числами прописью
                        {
                            tmp = numbers[i][j];                        //левые поля
                            tmp1 = words[w];                            //левые поля
                            tmp2 = numbers[i][numbers[i].Length - 1];   //Значение числа пропсью - тоже левое поле
 
                            if (numbers[i][j].ToLower() == words[w].ToLower())      //проверка на совпадение элемента массива из заданной строки с элементом массива из зубчатого массива
                            {
                                if (!(words[w] == "тысяч" || words[w] == "тысячи" || words[w] == "тысяча" ||              //проверка на соответствие значения words[w] != "тысяч" и т.д. просто лень везде переделывать == на != =)
                                     words[w] == "миллиона" || words[w] == "миллионов" || words[w] == "миллион" ||
                                     words[w] == "миллиарда" || words[w] == "миллиард" || words[w] == "миллиардов" ||
                                     words[w] == "триллион" || words[w] == "триллиона" || words[w] == "триллионов" ||
                                     words[w] == "триллиард" || words[w] == "триллиарда" || words[w] == "триллиардов" ||
                                     words[w] == "квадриллион" || words[w] == "квадриллиона" || words[w] == "квадриллионов" ||
                                     words[w] == "квинтиллион" || words[w] == "квинтиллиона" || words[w] == "квинтиллионов" ||
                                     words[w] == "секстиллион" || words[w] == "секстиллиона" || words[w] == "секстиллионов" ||
                                     words[w] == "септиллион" || words[w] == "септиллиона" || words[w] == "септиллионов" ||
                                     words[w] == "октиллион" || words[w] == "октиллиона" || words[w] == "октиллионов" ||
                                     words[w] == "нониллион" || words[w] == "нониллиона" || words[w] == "нониллионов" ||
                                     words[w] == "дециллион" || words[w] == "дециллиона" || words[w] == "дециллионов" ||
                                     words[w] == "ундециллион" || words[w] == "ундециллиона" || words[w] == "ундециллионов" ||
                                     words[w] == "ундециллион" || words[w] == "ундециллиона" || words[w] == "ундециллионов"))
                                {
                                    if (!Decimal.TryParse(numbers[i][numbers[i].Length - 1], out num[w])) num[w] = 0;       //если последний элемент внутреннего массива может быть преобразован в decimal, записываем его значение в num[w]
                                    flag = true;                                                                            //для выхода из внешнего цикла
                                }
                                else
                                {
 
                                    for (int d = trep == 0 ? 0 : w - trep; d < w; d++)                                      //если trep == 0, то это значит, что вхождения еще не было 
                                    {                                                                                       //и начинается сложение с нулевого элемента массива, 
                                        temp += num[d];                                                                     //иначе d равно разности w с предыдущим вхождением (когда words[w] == "тысяча", "руб", "коп" или что-то подобное)
                                    }                                                                                       //в данном случае words[w] == "тысяча" или более бОльшим значениям, поэтому умножения нет (см. дальше)
                                    numeric += temp * Decimal.Parse(numbers[i][numbers[i].Length - 1]);                     //тк word[w] = "тысяча" или подобное, происходит умножение на последний элемент внутреннего массива, где хранятся значения чисел прописью
                                    trep = w;                                                                               //задается индекс вхождения, с которого в дальнейшем будет производиться сумма
                                    temp = 0;                                                                               //очередное обнуление темпа... опять же, на всякий случай =) 
 
                                }
                                break;                                                                                      //выход из цикла
                            }
                            else continue;
                        }
                    }
                }
            }
 
 
 
            for (int w = 0; w < words.Length; w++)                                                                          //фор, для понимая вывода
            {
                Console.WriteLine($"{num[w]} ------ {words[w]}");
            }
 
            return numeric;
        }
 
        private static void Main(string[] args)
        {
            Test test = new Test();
            Console.WriteLine(test.RecipeToNum("двенадцать тысяч сто девяносто два руб пятьдесят три копейки"));
            Console.ReadLine();
 
        }
Добавлено через 18 минут
Скорее всего ошибка где-то в условии цикла
Код
for (int w = 0; w < words.Length; w++)
но где, в чем и как исправить - не понимаю...
0
управление сложностью
1687 / 1300 / 259
Регистрация: 22.03.2015
Сообщений: 7,545
Записей в блоге: 5
12.04.2018, 11:21 4
Цитата Сообщение от Zodt Посмотреть сообщение
но где, в чем и как исправить - не понимаю...
отладчик вам в помощь
0
170 / 91 / 71
Регистрация: 10.05.2014
Сообщений: 432
12.04.2018, 11:59  [ТС] 5
Все таки нашел ошибку, и она настолько смешная, что прям даже обидно=)
вместо
Код
w - trep
надо было ставить
Код
w - (w - trep)
0
170 / 91 / 71
Регистрация: 10.05.2014
Сообщений: 432
16.04.2018, 10:43  [ТС] 6
Точнее просто
Код
trep
Может кому-то пригодится. Массив сюда вставлять не стал, он в комментах выше


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
        public static decimal RecipeToNum(string _text)
        {
            _text = _text.Replace(".", ",");
            if (decimal.TryParse(_text, out decimal numeric)) return numeric; //итоговое число
            var reg = new Regex(@"[,\/\\\(\)\-\+\=\*\&\?\^\%\$\#;" + '"' + @"'`~@\[\{\]\}\!\№\:]");
            _text = reg.Replace(_text, "");
            var trep = 0;
            var flag = false;                                      //небольшие костыли =)
            var words = _text.Split();                          //массив заданных чисел прописью
            decimal temp = 0;
            var num = new decimal[words.Length];              //массив, в который преобразуются числа прописью в числа чифрами
                
            for (var w = 0; w < words.Length; w++)                  //прогон по массиву заданных чисел прописью 
                switch (words[w])
                {
                    case "рубль":
                    case "рублей":
                    case "рубля":
                    case "руб":
                        for (var d = trep; d < w; d++)            //если trep == 0, то это значит, что вхождения еще не было и начинается сложение с нулевого элемента массива, 
                            numeric += num[d];                    //иначе d равно разности w с предыдущим вхождением (когда words[w] == "тысяча", "руб", "коп" или что-то подобное)
                        trep = w;                                 //задается индекс вхождения, с которого в дальнейшем будет производиться сумма
                        continue;
                    case "копейка":
                    case "копейки":
                    case "копеек":
                    case "коп":
                        for (var d = trep; d < w; d++)            //если trep == 0, то это значит, что вхождения еще не было и начинается сложение с нулевого элемента массива, 
                            temp += num[d];                       //иначе d равно разности w с предыдущим вхождением (когда words[w] == "тысяча", "руб", "коп" или что-то подобное)
                        numeric += temp == 0 ? 0 : temp / 100;    //сложение всех элементов стоящих между "руб" и "коп" с проверкой на равенство нулю
                        trep = w;                                 //задается индекс вхождения, с которого в дальнейшем будет производиться сумма
                        temp = 0;                                 //очередное обнуление темпа... опять же, на всякий случай =) 
                        break;
                    default:
                        if (decimal.TryParse(words[w], out num[w]))        
                        {
                            continue;
                        }   //проверка задано ли числом данный элемент массива
                        else
                        {
                            foreach (string[] t in Numbers)
                            {
                                //Проверка на выход из цикла
                                if (!flag)
                                {
                                    for (var j = 0;               //прогон по элементам внутреннего массива с числами прописью
                                        j < t.Length - 1;
                                        j++) 
                                    {
                                        //проверка на совпадение элемента массива из заданной строки с элементом массива из зубчатого массива
                                        if (String.Equals(t[j], words[w], StringComparison.CurrentCultureIgnoreCase)) 
                                        {
                                            //проверка на соответствие значения words[w] != "тысяч" и т.д. просто лень везде переделывать == на != =)
                                            if (!(words[w] == "тысяч" || words[w] == "тысячи" ||
                                                  words[w] == "тысяча" ||                               
                                                  words[w] == "миллиона" || words[w] == "миллионов" ||
                                                  words[w] == "миллион" ||
                                                  words[w] == "миллиарда" || words[w] == "миллиард" ||
                                                  words[w] == "миллиардов" ||
                                                  words[w] == "триллион" || words[w] == "триллиона" ||
                                                  words[w] == "триллионов" ||
                                                  words[w] == "триллиард" || words[w] == "триллиарда" ||
                                                  words[w] == "триллиардов" ||
                                                  words[w] == "квадриллион" || words[w] == "квадриллиона" ||
                                                  words[w] == "квадриллионов"))
                                            {
                                                if (!decimal.TryParse(t[t.Length - 1], out num[w])) num[w] = 0; //если последний элемент внутреннего массива может быть преобразован в decimal, записываем его значение в num[w]
                                                flag = true; //для выхода из внешнего цикла
                                            }
                                            else
                                            {
                                                for (var d = trep; d < w; d++)                    //если trep == 0, то это значит, что вхождения еще не было и начинается сложение с нулевого элемента массива, 
                                                    temp += num[d];                               //иначе d равно разности w с предыдущим вхождением (когда words[w] == "тысяча", "руб", "коп" или что-то подобное)
                                                numeric += temp * decimal.Parse(t[t.Length - 1]); //тк word[w] = "тысяча" или подобное, происходит умножение на последний элемент внутреннего массива, где хранятся значения чисел прописью
                                                trep = w;                                         //задается индекс вхождения, с которого в дальнейшем будет производиться сумма
                                                temp = 0;                                         //очередное обнуление темпа... опять же, на всякий случай =) 
                                                flag = true;                                      //для выхода из внешнего цикла
                                            }
                                            break; //выход из цикла
                                        }
                                    }
                                }
                                else
                                {
                                    //выход из цикла
                                    flag = false;       
                                    break;
                                }
                            }
                        }
                        break;
                }
 
            return numeric;                                             //итоговое число
        }
0
263 / 224 / 108
Регистрация: 09.12.2015
Сообщений: 652
16.04.2018, 15:34 7
Цитата Сообщение от Zodt Посмотреть сообщение
Массив сюда вставлять не стал, он в комментах выше
Вы про этот массив?
C#
1
2
3
4
5
string[][] numbers =
{
   new string[2] {"восемьдесять", "18"},
   new string[2] {"двесте", "200"}
};
Надеюсь, вы пофиксили эти два элемента в нём.
1
170 / 91 / 71
Регистрация: 10.05.2014
Сообщений: 432
16.04.2018, 17:46  [ТС] 8
Да, пару дней назад заметил) Но все равно спасибо)
0
171 / 106 / 51
Регистрация: 27.11.2015
Сообщений: 1,268
19.04.2018, 11:28 9
Zodt, кстати, а как вы смотрите на такой метод(если ещё актуально)?
Надо только доработать работу с копейками)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static void Main()
        {
            int nu = 1890, ne = 0, num = 0;
            int[] n = new int[20];
            string[] di = { "ноль", "один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять" };
            Console.WriteLine("число " + nu);
            Console.Write("число в словах:");
            do
            {
                ne = nu % 10;
                n[num] = ne;
                num++;
                nu /= 10;
            }
            while (nu > 0);
            num--;
            for (; num >= 0; num--)
                Console.Write(di[n[num]] + " ");
            Console.Read();
 
        }
0
170 / 91 / 71
Регистрация: 10.05.2014
Сообщений: 432
19.04.2018, 15:19  [ТС] 10
Цитата Сообщение от ShmelVG Посмотреть сообщение
Zodt, кстати, а как вы смотрите на такой метод?
Смотрю, что Вы сделали обратный алгоритм из "1890" получить "Одна тысяча восемьсот девяносто", а у меня задача была из "Одна тысяча восемьсот девяносто" получить "1890"! Но за попытку благодарю)
0
19.04.2018, 15:19
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.04.2018, 15:19
Помогаю со студенческими работами здесь

Число - прописью. Работа с простыми числами
Написать программу, которая считывает с клавиатуры предложения и заменяет «0», «1» … «9» на...

Как вывести число (сумма, количество) прописью ?
Здраствуйте, как можно форматнуть число : 123.45 -&gt; &quot;сто двадцать три&quot; грн 45 коп 198.10 -&gt; &quot;сто...

Записать прописью ближайшее к заданному четное число из введенного диапазона
Я думаю, что ошибка возникает из-за того, что переменная ch видна только в пределах своих циклов,...

С клавиатуры вводится число от 1 до 1000. Программа должна вывести его прописью
Задача: с клавиатуры вводится число от 1 до 1000. Программа должна вывести его прописью. using...

Число прописью
Здравствуйте! Помогите пожалуйста с моей проблемой. Нашел код для преобразования числа прописью, но...

Число прописью и оператор switch
Помогите дописать код: есть диапазон от 10 до 40. Например пользователь вводит 19 : выводиться...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru