Ниже кусок кода, точнее функция, переделывающая число,записанное цифрами (до одного миллиарда), в числительное (число записанное буквами, порядковое). Я уверен что оптимизировать это ещё как можно, так как скорость не приемлимая (на асме запарюсь писатьЖ)))), поэтому прошу помочь в этом нелёгком оптимизационном деле, с чего начать то?
S4urp8n Case замени на выбор из массива. Так что бы в массиве были все числа из разряда записанные пропесью. Для младших можно все два забить.
а почему бы не составить таблицу типа bin_number, char_name[], но упорядочить в ней все строки по алфавиту и собрать все указатели на bin_number в массив, тогда можно предположить следующий вариант поиска сравниваем символ i текущей строки, если он совпадает, то переходим к следующему, если нет, то к следующей строке. когда найдешь пробел, то сравниваешь всю строку целиком. Код (Text): я не буду все упорядочивать, но вот так mas dd v0, v1, ... v0 dd 0 db "НОЛЬ " ... mov ebp, str mov edx, ebp xor edi, edi xor esi, esi @@: mov ebx, [mas+edi*4] lp: mov al, [ebx+esi+4] cmp al, [ebp] jz @f inc edi jmp @b @@: cmp al, 32 jz @f inc ebp inc esi jmp lp @@: mov esi, edx mov ecx, ebp sub ecx, edx mov edi, [mas+edi*4] add edi, 4 repe cmpsb jnz @f ;все ок ret @@: ;error ret ADD: главное чтобы указатели в массиве mas указывали на структуры в алфавитном порядке, а не как у меня с 0
S4urp8n Когда-то очень давно писал для друга. С подробными комментариями. Не припоминаю, чтобы были проблемы с быстродействием. Поддерживает числа до 10^36, включая десятичные дроби. Код (Text): //Библиотека содержит функции ввода-вывода #include <stdio.h> //Библиотека содержит функции для работы со строками #include <string.h> //Библиотека содержит функцию int atoi (const char *) #include <stdlib.h> //Библиотека содежит функцию int getch () #include <conio.h> //Функция перевода строки из кодировки Windows в кодировку DOS char *todos(char *str); //Функция преобразования целого положительного числа в текстовое //представление void convert(char *number); //Функция перевода тройки цифр в текстовое представление void conv3(char *number, int trion); //Функция дописывания статуса тройки цифр (тысяча, миллион и т.д.) void conv3name(char *number, int trion); //Функция дописывания статуса дробной части (десятая, сотая, //тысячная, десятитысячная и т.д.) void addSubZero(int numSigns, bool female); //Переменная, определяющая, является ли исходное число целым bool isInt; //Строка для результата работы программы char numstr[1500] = {0}; //Массивы строк, содержащие соответствующие наименования базовых //чисел const char nums1[][13]={"один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять", "десять", "одиннадцать", "двенадцать", "тринадцать", "четырнадцать", "пятнадцать", "шестнадцать", "семнадцать", "восемнадцать", "девятнадцать"}; const char nums2[][12]={"двадцать", "тридцать", "сорок", "пятьдесят", "шестьдесят", "семьдесят", "восемьдесят", "девяносто"}; const char nums3[][10]={"сто", "двести", "триста", "четыреста", "пятьсот", "шестьсот", "семьсот", "восемьсот", "девятьсот"}; const char great[][12]={"тысяч", "миллион", "миллиард", "триллион", "квадриллион", "квинтиллион", "секстиллион", "септиллион", "октиллион", "нониллион", "дециллион"}; //С этой функции начинается работа программы void main() { //Строка-приглашение для ввода пользователю char invit[]="Введите число "; //Строка, содержащая исходное число и указатель на нее char numbuf[80]; char *number = numbuf; //Выводим приглашение для ввода, предварительно преобразовав //его в DOS-кодировку printf(todos(invit)); //Первые два байта строки, содержащей исходное число //забиваем символом "0" number[0] = '0'; number[1] = '0'; //Смещаем указатель на строку на эти два байта number += 2; //Читаем с клавиатуры исходное число scanf ("%s", number); //Проверяем, целое ли введенное число, и записываем результат //проверки в переменную isInt isInt = (strchr(number, '.') == 0 && strchr(number, ',') == 0); //Если число дробное, то... if (!isInt) //...заменяем разделитель дробной и целой части //нуль-терминатором *(strchr(number, '.') != 0 ? strchr(number, '.') : strchr(number, ',')) = 0; //Если исходное число не нуль, то вызываем функцию //преобразования числа в текстовое представление, а... if (*number!='0') convert(number); //если нуль, то добавляем в строку-результат текст "нуль " else strcat(numstr, "нуль "); //Если число дробное, то... if (!isInt) { //...переводим и дробную часть в текстовое представление //Учитываем род, число и падеж целой части if (number[strlen(number)-1] == '1' && number[strlen(number)-2] != '1') strcat (numstr, "целая "); else strcat (numstr, "целых "); //Смещаем указатель на дробную часть number += strlen(number)+1; //Два предшествующих байта забиваем символами "0" number[-1] = '0'; number[-2] = '0'; //Рассматриваем, как отдельный случай, когда дробная //часть нулевая: if (atoi(number) == 0 && strlen(number) != 0) strcat (numstr, "нуль "); else convert(number); //Дописываем статус дробной части addSubZero (strlen(number), number[strlen(number)-1] == '1' && number[strlen(number)-2] != '1'); } //Выводим сформированную строку на экран printf("%s\n", todos(numstr)); //Предлагаем пользователю завершить работу с программой printf("Press any key to continue\n"); //Ожидаем его реакцию getch(); } //Функция преобразования целого положительного числа в текстовое //представление void convert(char *number) { //Объявляем счетчик троек цифр и хранитель длины строки-числа int counter, numlen; //Запоминаем длину строки-числа numlen = strlen(number); //Забиваем строку-число спереди нужным числом нулей if (numlen%3 != 0) number -= 3-numlen%3; //Обновляем длину строки-числа numlen = strlen(number); //Перебираем тройки цифр числа и для каждой тройки... for (counter = 0; counter <= numlen-1; counter+=3) { //...находим ее текстовое представление и... conv3(number+counter, (numlen-counter)/3-1); //...определяем ее статус в числе conv3name(number+counter, (numlen-counter)/3-1); } } //Функция перевода тройки цифр в текстовое представление void conv3(char *number, int trion) { //Переменная-тройка цифр-строка char sTrio[4] = {0}; //Переменная-тройка цифр-число int iTrio; //Получаем тройку цифр, как строку и как число strncpy(sTrio, number, 3); iTrio = atoi(sTrio); //Если это число больше сотни, то... if (iTrio >= 100) { //...дописываем текстовое представление разряда сотен //числа strcat(numstr, nums3[iTrio/100-1]); //Ставим в конце пробел strcat(numstr, " "); } //Рассматриваем, как отдельные случаи, когда //разряд десятков больше единицы и... if (iTrio%100 >= 20) { //Дописываем текстовое представление цифры разряда //десятков strcat(numstr, nums2[iTrio/10%10-2]); //Ставим пробел strcat(numstr, " "); //Если у разряда единиц есть текстовое представление, то... if (iTrio%10 >= 1) { //...его тоже дозаписываем в строку-результат strcat(numstr, nums1[iTrio%10-1]); //Ставим пробел strcat(numstr, " "); } } //...когда меньше или равен единице else { //Для случаев, когда это необходимо, дописываем текстовое //представление оставшейся части числа if ((iTrio > 1 || (trion == 0 && iTrio >= 1)) && iTrio%100 != 0) { strcat(numstr, nums1[iTrio%100-1]); strcat(numstr, " "); } } } //Функция дописывания статуса тройки цифр (тысяча, миллион и т.д.) void conv3name(char *number, int trion) { //Переменная-тройка цифр-строка char sTrio[4] = {0}; //Переменная-тройка цифр-число, переменная-хранитель //длины числа-строки int iTrio, numstrlen; //Получаем тройку цифр, как строку и как число strncpy(sTrio, number, 3); iTrio = atoi(sTrio); //Если тройка цифр равна нулю, то статус не описывается if (iTrio == 0) return; //Запоминаем длину числа-строки numstrlen = strlen(numstr); //Если это первая тройка чисел, то для дробных чисел... if (trion == 0 && !isInt) { //...согласуем в роде, числе и падеже текстовое представление //тройки цифр и текстовое представление ее статуса if (iTrio%10 == 1 && iTrio%100 != 11) { //Преобразуем "один" в "одна" numstr[numstrlen-2] = 'a'; numstr[numstrlen-3] = 'н'; } if (iTrio%10 == 2 && iTrio%100/10 != 1) { //Преобразуем "два" в "две" numstr[numstrlen-2] = 'е'; } } //Тройка цифр-тысячи, рассматривается, как отдельный случай, т.к. //тысяча — единственный статус в женском роде if (trion == 1) { //...согласуем в роде, числе и падеже текстовое представление //тройки цифр и текстовое представление ее статуса if (iTrio%10 == 1 && iTrio > 20) { //Преобразуем "один" в "одна" numstr[numstrlen-2] = 'a'; numstr[numstrlen-3] = 'н'; } if (iTrio%10 == 2 && iTrio%100/10 != 1) { //Преобразуем "два" в "две" numstr[numstrlen-2] = 'е'; } //Дописываем текстовое представление статуса strcat(numstr, great[0]); //В требуемых случаях меняем... if (iTrio%100 <= 4 || iTrio%100 >= 21) { //..."тысяч" на "тысяча" или... if (iTrio%10 == 1) strcat(numstr, "а"); //...на "тысячи" if (iTrio%10 >= 2 && iTrio%10 <= 4) strcat(numstr, "и"); } //Дописываем пробел strcat(numstr, " "); } //Остальные статусы(миллион, миллиард и т.д.) рассматриваются //вместе (они все мужского рода) if (trion > 1) { //Дописываем текстовое представление статуса strcat(numstr, great[trion-1]); //В требуемых случаях согласуем текстовое представление //статуса с текстовым представлением соответствующей //тройки чисел в роде, числе и падеже if (iTrio%10 == 0 || iTrio%10 >= 5 || iTrio%100/10 == 1) strcat(numstr, "ов"); else if (iTrio%10 != 1) strcat(numstr, "а"); //Дописываем пробел strcat(numstr, " "); } } //Функция дописывания статуса дробной части (десятая, сотая, //тысячная, десятитысячная и т.д.) void addSubZero(int numSigns, bool female) { //Если число знаков дробной части... switch (numSigns) { //...нуль, то у пустой дробной части нет и статуса case 0: return; //...один, то это десятые доли case 1: strcat(numstr, "десят"); break; //...два — сотые доли case 2: strcat(numstr, "сот"); break; //...остальные случаи default: //Для числа знаков, кот. дают в остатке при делении на //три единицу статусы: десятитысячные доли, десятимиллионные //доли и т.д if (numSigns%3 == 1) strcat(numstr, "десяти"); //Аналогично: стотысячные, стомиллионные и т.д. доли if (numSigns%3 == 2) strcat(numstr, "сто"); //Дописываем следующие части текстового представления //статуса дробной части strcat (numstr, great[numSigns/3-1]); strcat (numstr, "н"); } //Согласуем в роде, числе и падеже текстовое представление //статуса дробной части с текстовым представлением дробной части strcat (numstr, female ? "ая" : "ых"); } //Функция перевода строки из кодировки Windows в кодировку DOS char *todos(char *str) { unsigned char ch; short i=0; do { ch=str[i]; if(ch >= 128) { if(ch >= 192 && ch <= 239) ch -= 64; else if(ch >= 240) ch -= 16; else if(ch == 185) ch = 252; else if(ch == 168) ch = 240; else if(ch == 184) ch = 241; str[i] = ch; } i++; } while(ch != 0); return str; } P.S. Правильно не "ноль", а "нуль".
Спасибо всем кто ответил. ) Напоследок хотел спросить как функция будет работать быстрее, если её одну вызвать, либо если разбить её на подфункции и вызвать по подряд их все?