29 апр. 2014 г.

4 апр. 2014 г.

Пролог

Аналогов в Беларуси просто нет. Ниже приведен фрагмент кода программы расчета заработной платы на языке Prolog . Работает в режиме промышленной эксплуатации на двух крупных предприятиях (более 1000 работников на каждом).

% среднедневной заработок по сотруднику (по среднечасовому)
% - для отпусков
calc_avg_wage(Scope, PK, AvgWage, Rule) :-
Rule = by_avg_houre,
% правило действительно
is_valid_rule(Scope, PK, _, Rule),
% подготовка временных данных для расчета
prep_avg_wage(Scope, PK, Periods),
% взять заработок
findall( Wage,
% за каждый период проверки
( member(Y1-M1, Periods),
% взять данные по заработку
get_month_wage(Scope, PK, Y1, M1, _, Wage) ),
% в список заработков
Wages ),
% итоговый заработок
sum_list(Wages, Amount),
% взять часы
findall( THoures,
% за период проверки
( member(Y2-M2, Periods),
% взять данные по часам за месяц
get_month_norm_tab(Scope, PK, Y2-M2, _, _, _, THoures)
),
% в список часов
Durations),
% всего часов по табелю
sum_list(Durations, TotalTab),
% среднечасовой заработок
catch( AvgHoureWage is Amount / TotalTab, _, fail ),
% разложить первичный ключ
PK = [pEmplKey-EmplKey, pFirstMoveKey-FirstMoveKey],
% всего часов по графику за расчетный год
get_data(Scope, in, usr_wg_TblYearNorm, [
fEmplKey-EmplKey, fFirstMoveKey-FirstMoveKey,
fWHoures-TotalNorm]),
% среднемесячное количество расчетных рабочих часов
AvgMonthNorm is TotalNorm / 12,
% среднемесячное количество календарных дней
get_param(Scope, in, pAvgDays-AvgDays),
% среднедневной заработок
catch( AvgWage0 is AvgHoureWage * AvgMonthNorm / AvgDays, _, fail ),
AvgWage is round(AvgWage0),
!.

3 апр. 2014 г.

Как избежать расхождений при делении и последующем округлении массы единицы сырья или товара

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

Пример: учет ведется с точностью до 0.1 кг, на весы загнали три единицы и получили общую массу 511.1 кг. Простое деление даст нам 170.3666666666667 кг на единицу или 170.4 кг после округления. Когда в итоговом отчете три единицы посуммируются получится 511.2 кг, т.е. возникнет расхождение с исходными показаниями весов.

Правильно в данном случае поступить следующим образом:

  1. Общую массу перевести в целочисленное количество минимальных единиц. В нашем случае такой единицей будет 0.1 кг, соответственно,
    511.1 кг = 5111 по 0.1 кг
  2. Целочисленно разделить полученное число на количество единиц в партии:
    5111 div 3 = 1703 = D
  3. Вычислить остаток от целочисленного деления:
    5111 mod 3 = 2 = M
  4. Для произвольных M единиц в партии принять учетную массу (D + 1) для остальных -- D.
Т.е. в нашем случае получится следующая учетная масса каждой единицы в партии:
  1. (1703 + 1) * 0.1 = 170.4 кг
  2. (1703 + 1) * 0.1 = 170.4 кг
  3. 1703 * 0.1 = 170.3 кг
В сумме -- ровно 511.1 кг.

1 апр. 2014 г.

На заметку. Если в процедуре встретится конструкция:
...
INSERT INTO table1 
  SELECT * FROM table2;
...
то возникнет зависимость между процедурой и всеми полями из table2, хотя они тут и не прописаны явно.