Форум: "Прочее";
Текущий архив: 2014.12.21;
Скачать: [xml.tar.bz2];
ВнизУпростить числосклонятор до полной нечитабельности Найти похожие ветки
← →
MBo © (2014-05-20 22:13) [0]Писал велосипедик для правильного склонения во множественном числе, в процессе думал об использовании открытого массива вместо трех строковых констант и избавления от case, но это чревато лишней проверкой его корректности, и не нашёл компактного выражения для вычисления индекса:
0 -> 0
1..3- > 1
4...13 -> 2
C масками и переводом в логические выражения и назад в арифметику получалось развесисто. Может, кому придёт в голову интересный вариант.
Сам полуобфусцированный велосипедик:
//usage: PluralWord(3, "рубль", "рубля", "рублей");
function PluralWord(Amount: Integer; const One, Two, Five: string): string;
begin
Amount := Abs(Amount);
case 4 * Ord(1 = (Amount mod 100) div 10) + (Amount - 1) mod 10 of
0: Result := One;
1..3: Result := Two;
else
Result := Five;
end;
end;
← →
antonn © (2014-05-20 22:24) [1]я в вебе такое юзаю:
foo(30,array("пользователь", "пользователя", "пользователей"))
function foo($number, $titles){
$cases = array (2, 0, 1, 1, 1, 2);
return $titles[ ($number%100>4 && $number%100<20)? 2 : $cases[min($number%10, 5)] ];
}
← →
MBo © (2014-05-20 22:39) [2]Ага, несколько другая логика, но тоже довольно много внутри накручено, а тернарный оператор скрадывает объём выражения
← →
Дмитрий СС (2014-05-20 22:52) [3]Не проверял и навскидку:
Wrd: array[0..2] of String = ("рублей", "рубль", "рубля");
...
Amount := Abs(Amount) mod 100;
Result := Wrd[Ord(
(Amount > 10) and (Amount < 20)
) * (
Ord(( (Amount + 3) mod 10) >= 6)
+ Ord(( (Amount + 3) mod 10) >= 7)
)]
← →
Дмитрий СС (2014-05-20 22:53) [4]Вижу что уже неправильно знаки стоят, надеюсь идея понятна
← →
Омлет © (2014-05-20 23:21) [5]
function PluralWord_omlet(Amount: Integer; const One, Two, Five: string): string;
var
n: integer;
begin
Amount := Abs(Amount);
n := Amount mod 10;
if (n > 4) or (n = 0) or (Amount mod 100 - n = 10) then
Result := Five
else if n > 1 then
Result := Two
else
Result := One;
end;
← →
Омлет © (2014-05-20 23:36) [6]Только вот задачу не очень понял. Нужно сделать нечитабельно? Или неоптимально? Зачем это обфусцировать?
← →
Sha © (2014-05-21 00:15) [7]var c1, c2: cardinal;
begin;
c2:=abs(Amount);
c1:=c2 mod 10;
c2:=c2 mod 100;
if (c1=0) or (c1>=5) or (c1+10=c2) then Result:=Five
else if (c1=1) then Result:=One
else Result:=Two;
end;
← →
Sha © (2014-05-21 00:18) [8]> Омлет © (20.05.14 23:21) [5]
практически совпало)
я свою выдернул из текущего проекта
← →
Юрий Зотов © (2014-05-21 00:22) [9]Проверочное слово - кочерга.
:o)
← →
KSergey © (2014-05-21 08:00) [10]> 0 -> 0
> 1..3- > 1
> 4...13 -> 2
Это 13 байт статического массива + простейшая команда доступа к массиву по индексу.
Во сколько байт скомпилируются приведенные выше куски кода?
И во сколько тактов процессора выполнятся?
Если входной параметр может выходить за диапазон [0..13] - тогда расширить таблицу до 16 элементов [0..15], в 14 и 15 запихать что-то разумное (видимо тоже 2, если я правильно понял) - и во входном параметре оставить 4 младших бита одной логической операцией.
Я к чему: все эти заумные алгоритмы и упражнения - абсолютно зряшнее времяубивание в рамках конечного времени жизни. Не в них то, что ожидается от программиста.
← →
MBo © (2014-05-21 08:02) [11]>Только вот задачу не очень понял. Нужно сделать нечитабельно? Или неоптимально? Зачем это обфусцировать?
Набор ифов понятнее. А так - разные подходы интересно посмотреть (был когда-то впечатлен кучей невероятных методов посчитать DayOfWeek - с десяток не самых отмороженных есть в Pascal SWAG).
← →
Омлет © (2014-05-21 08:12) [12]> Sha © (21.05.14 00:15) [7]
Для 60% чисел mod 100 считать не нужно, поэтому мой вариант эффективнее )
← →
Inovet © (2014-05-21 08:14) [13]Посмотрел свой старый велосипед, ничего оригинального.
void __fastcall NumSpellE(__int64 n, String &w, Gender g, __int64 e, String s1, String s2, String s3)
{
__int64 t;
t = n / e; t %= 1000;
if (n) {
NumSpell3(t, w, g);
}
else {
w = L"ноль";
}
String s;
if (t > 0 || e == 1) {
t %= 100;
if (t < 11 || t > 19) {
switch (t % 10) {
case 1: s = s1; break;
case 2:
case 3:
case 4: s = s2; break;
default: s = s3;
}
}
else s = s3;
}
if (!w.IsEmpty() && !s.IsEmpty()) w += " ";
w += s;
}
← →
Омлет © (2014-05-21 08:25) [14]> KSergey © (21.05.14 08:00) [10]
> Не в них то, что ожидается от программиста.
(c) автор IncDay ))
← →
KSergey © (2014-05-21 08:57) [15]Ну вот, нарвался на авторские отчисления....
Куда гонорар автору засылать?
← →
Sha © (2014-05-21 14:15) [16]> Омлет © (21.05.14 08:12) [12]
> Для 60% чисел mod 100 считать не нужно, поэтому мой вариант эффективнее )
ну, тогда так:function IntToName125Mod(i: integer): integer;
const
b: array[0..99] of byte=(
//0 1 2 3 4 5 6 7 8 9
2,0,1,1,1,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2,
2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2);
begin;
Result:=b[abs(i) mod 100];
end;
или даже так:function IntToName125NoMod(i: integer): integer;
const
b: array[0..99] of byte=(
//0 1 2 3 4 5 6 7 8 9
2,0,1,1,1,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2,
2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2);
var
j, k: integer;
begin;
//i:=abs(i);
j:=-(i shr 31);
i:=i xor j - j;
//i:=i-100*N;
j:=i shr 7;
k:=i shr 20;
i:=i and $1FF;
j:=j and $7FFC;
k:=k and -4;
j:=j * 3;
i:=i + k;
i:=i + j;
//i:=i mod 100 для 0<=i<1024*100
j:=(i + 1) * $A3D7 shr 22 * 100;
i:=i - j;
Result:=b[i];
end;
← →
Омлет © (2014-05-21 14:33) [17]О, вот теперь действительно обфускация )
← →
Rouse_ © (2014-05-21 18:43) [18]Финтифлюшки это все :)
function PluralWord(Amount: Integer; const One, Two, Five: string): string;
begin
Result := "руб.";
end;
← →
brother © (2014-05-21 18:53) [19]> "рубль", "рубля", "рублей"
выводить через #
← →
Sha © (2014-05-22 01:00) [20]Немного ускорил:
const
Rests: array[0..99] of ShortInt=(
//0 1 2 3 4 5 6 7 8 9
2,0,1,1,1,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2,
2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2, 2,0,1,1,1,2,2,2,2,2);
function IntToName125Mod(i: integer): integer; overload;
begin;
Result:=Rests[abs(i) mod 100];
end;
function IntToName125NoMod(i: integer): integer; overload;
var
j, k: integer;
begin;
//i:=abs(i);
j:=-(i shr 31);
i:=i xor j - j;
//i:=i-100*N;
j:=i shr 10;
k:=i shr 20;
i:=i and $0FFF; //биты 0..11
j:=j and $0FFC; //биты 12..21 -> 2..11
k:=k and $0FFC; //биты 22..31 -> 2..11
i:=i - j;
i:=i + k + 4100;
//i:=i mod 100 для 0<=i<1024*100
j:=(i + 1) * $A3D7 shr 22 * 100;
i:=i - j;
Result:=Rests[i];
end;
Аналог для int64:function IntToName125Mod(i64: int64): integer; overload;
begin;
Result:=Rests[abs(i64) mod 100];
end;
function IntToName125NoMod(i64: int64): integer; overload;
var
i, j: integer;
begin;
i64:=abs(i64);
//i:=i-100*N;
j:=i64;
i:=j and $0FFF //биты 0..11
- j shr 10 and $0FFC //биты 12..21 -> 2..11
+ j shr 20 and $0FFC //биты 22..31 -> 2..11
+ 32000;
j:=i64 shr 32;
if j<>0 then i:=i
- j shl 2 and $0FFC //биты 32..41 -> 2..11
+ j shr 8 and $0FFC //биты 42..51 -> 2..11
- j shr 18 and $3FFC;//биты 52..63 -> 2..13
//i:=i mod 100 для 0<=i<1024*100
j:=(i + 1) * $A3D7 shr 22 * 100;
i:=i - j;
Result:=Rests[i];
end;
Как только начинаем работать со строками,
громадная разница в скорости скукоживается примерно до 2х раз:const
Names: array[0..2] of string= ("кочерга", "кочерги", "кочерег");
//пример вызова Memo1.Lines.Add(Format("%d %s",[i,IntToName125String(i,@Names[0])]));
function IntToName125String(i64: int64; Names: pString): string; overload;
var
i, j: integer;
begin;
i64:=abs(i64);
//i:=i-100*N;
j:=i64;
i:=j and $0FFF //биты 0..11
- j shr 10 and $0FFC //биты 12..21 -> 2..11
+ j shr 20 and $0FFC //биты 22..31 -> 2..11
+ 32000;
j:=i64 shr 32;
if j<>0 then i:=i
- j shl 2 and $0FFC //биты 32..41 -> 2..11
+ j shr 8 and $0FFC //биты 42..51 -> 2..11
- j shr 18 and $3FFC;//биты 52..63 -> 2..13
//i:=i mod 100 для 0<=i<1024*100
j:=(i + 1) * $A3D7 shr 22 * 100;
i:=i - j;
inc(Names,Rests[i]);
Result:=Names^;
end;
function IntToName125StringMod(i64: int64; Names: pString): string; overload;
begin;
inc(Names,Rests[abs(i64 mod 100)]);
Result:=Names^;
end;
procedure TForm1.Button1Click(Sender: TObject);
const
Count= 20000000;
var
t: array[0..2] of cardinal;
i: integer;
begin;
t[0]:=GetTickCount;
for i:=0 to Count-1 do IntToName125String(int64(MaxInt)*4,@Names[0]);
t[1]:=GetTickCount;
for i:=0 to Count-1 do IntToName125StringMod(int64(MaxInt)*4,@Names[0]);
t[2]:=GetTickCount;
Memo1.Lines.Add(IntToStr(t[1]-t[0]));
Memo1.Lines.Add(IntToStr(t[2]-t[1]));
end;
← →
Владислав © (2014-05-22 01:24) [21]Как автоматически просклонять "1 рубль", "2 рубля", "5 рублей" и т.д.:
function(Amount: Integer): string;
begin
Result := "RUB " + IntToStr(Amount);
end;
Очень много валют так склоняется. ;)
← →
Sha © (2014-05-22 01:44) [22]жаль велосипеды и очень много других вещей так не склоняются
← →
Омлет © (2014-05-22 12:07) [23]> Sha © (22.05.14 01:00) [20]
Жесть )
← →
MBo © (2014-05-22 12:12) [24]>Очень много валют так склоняется. ;)
Мне нужно было вывести фразы типа "1 поток завершён, 2 потока завершены..."
← →
oldman © (2014-05-22 14:50) [25]
> MBo © (22.05.14 12:12) [24]
"Потоков завершено: "+IntToStr(i)
← →
Германн © (2014-05-22 15:00) [26]
> "Потоков завершено: "+IntToStr(i)
>
Магнитофон импортный. Два. (с)
← →
Sha © (2014-05-22 15:31) [27]))
"Потоков завершено: "+IntToStr(i)+" шт."
← →
Омлет © (2014-05-22 20:38) [28]"Несколько потоков завершено" )
← →
brother © (2014-05-22 20:39) [29]Сколько-то чего-то возможно завершилось...
:)
← →
brother © (2014-05-22 20:42) [30]> возможно
заменить на: скорее всего
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2014.12.21;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.003 c