楼主: denver
5133 26

关于先进先出(FIFO)的SAS实现 [推广有奖]

贵宾

六级木匠

已卖:776份资源

学科带头人

74%

还不是VIP/贵宾

-

威望
1
论坛币
190011 个
通用积分
7165.1540
学术水平
564 点
热心指数
508 点
信用等级
506 点
经验
66338 点
帖子
1490
精华
12
在线时间
1451 小时
注册时间
2004-11-17
最后登录
2026-1-4

初级学术勋章 初级热心勋章 初级信用勋章 中级学术勋章 中级热心勋章 高级学术勋章

楼主
denver 发表于 2013-1-27 14:12:50 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
先进先出原则在金融和会计领域有广泛的应用,但是一直没有找到SAS关于这方面的程序,故提问如下:

Type

Quantity

Price

Cost

Buy

100

$1.20

$120.00

Buy

50

$1.60

$80.00

Sell

(120)

 

($152.00)

Sell

(12)

 

($19.20)

Buy

15

$1.10

$16.50

Buy

40

$1.20

$48.00

Sell

(70)

 

($89.70)

Buy

50

$1.15

$57.50

Sell

(30)

 

($34.65)

Sell

(10)

 

($11.50)

上表是一件商品的买卖记录。商家先后买入了100和50件商品,然后卖出120件,安装先进先出的原则,卖出的商品中分别来自于第一次购买的100件和第二次购买的50件中的20件,因此,实现的销售成本是100*1.2+20*1.6=152,之后的以此类推
请问上述功能应该如何用SAS实现?谢谢
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:FIFO Ifo Quantity quant Price 成本 程序 会计 记录 领域

已有 2 人评分学术水平 热心指数 信用等级 收起 理由
pobel + 2 + 2 + 2 Good question!!
webgu + 1 + 1 + 1 鼓励积极发帖讨论

总评分: 学术水平 + 3  热心指数 + 3  信用等级 + 3   查看全部评分

本帖被以下文库推荐

Denver大家一起读Paper系列索引贴:
https://bbs.pinggu.org/thread-1430892-1-1.html

沙发
pobel 在职认证  发表于 2013-1-27 16:21:06
data test;
    infile cards missover;
    input Type $ Quantity  Price : dollar12.2  Cost : dollar12.2 ;
        format price cost dollar12.2;
        cards;
Buy 100  $1.20  $120.00
Buy 50  $1.60  $80.00
Sell 120
Sell 12
Buy 15  $1.10  $16.50
Buy 40  $1.20 $48.00
Sell 70
Buy 50  $1.15  $57.50
Sell 30
Sell 10
;

data test1;
   set test(keep=type quantity);
   where type="Sell";
   q_out=quantity;
   do while (q_out>0);
      if q_in<=0 or _n_=1 then set test(where=(_type="Buy") rename=(quantity=q_in type=_type));
          if q_out>q_in then do;
                          cost1=sum(cost1,price*q_in);
                         q_out=q_out-q_in;
                         q_in=0;
                end;
          else do;
                 cost1=sum(cost1,price*q_out);
                 q_in=q_in-q_out;
                 q_out=0;
                 p_in=price;
          end;
   end;
run;

     
data wanted;
    set test;
        if type="Sell" then do;
                set test1 (keep= type cost1);
               cost=cost1;
        end;
        drop cost1;
run;
已有 3 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
Imasasor + 80 + 60 + 1 + 1 + 1 我很赞同
denver + 100 + 5 + 5 + 5 NB!
webgu + 3 + 3 + 3 精彩帖子

总评分: 经验 + 180  论坛币 + 60  学术水平 + 9  热心指数 + 9  信用等级 + 9   查看全部评分

和谐拯救危机

藤椅
denver 发表于 2013-1-27 23:07:05
pobel 发表于 2013-1-27 16:21
data test;
    infile cards missover;
    input Type $ Quantity  Price : dollar12.2  Cost : dollar ...
继续问一下,如果是多种商品的话就应该写循环了吧,比如有个id来区分是商品1还是商品2,这个循环应该怎么写呢?如
id

Type

Quantity

Price

1

Buy

100

$1.20

1

Buy

50

$1.60

1

Sell

(120)

 

1

Sell

(12)

 

1

Buy

15

$1.10

1

Buy

40

$1.20

1

Sell

(70)

 

1

Buy

50

$1.15

1

Sell

(30)

 

1

Sell

(10)

 

2

Buy

100

$1.20

2

Sell

(70)

 

2

Buy

50

$1.15

2

Sell

(30)

 

2

Sell

(10)

 

Denver大家一起读Paper系列索引贴:
https://bbs.pinggu.org/thread-1430892-1-1.html

板凳
jingju11 发表于 2013-1-28 01:07:00
denver 发表于 2013-1-27 23:07
继续问一下,如果是多种商品的话就应该写循环了吧,比如有个id来区分是商品1还是商品2,这个循环应该怎么 ...
code not tested. Hopefully it works. Jingju

  1. data test2; drop s i n;
  2.   array qp[100,2] _temporary_; *arbiturary number 100,say <=100 times' buy for each id;
  3.   set test;
  4.   by id notsorted;
  5.   if (first.id) then n =.;  
  6.   if (type ='Buy') then do;
  7.     n ++1;
  8.     qp[n,1] =quantity; qp[n,2] =price;
  9.   end;
  10.   else if (type ='Sell') then do;
  11.     s =quantity;
  12.     do i =1 to n while(s >0);
  13.       if (qp[i,1] <=0) then continue;
  14.       s +(-qp[i,1]);      
  15.       if (s < 0) then do;
  16.         cost2 =sum(cost2, (s+qp[i,1])*qp[i,2]);
  17.         qp[i,1] =-s;   
  18.         end;
  19.       else if (s >=0) then do;
  20.         cost2 =sum(cost2, qp[i,1]*qp[i,2]);
  21.         qp[i,1] =0;
  22.         end;
  23.       end;
  24.     end;
  25. run;
复制代码


已有 4 人评分经验 学术水平 热心指数 信用等级 收起 理由
denver + 100 + 5 + 5 + 5 得和京剧好好学学数组的应用,厉害!
webgu + 1 + 1 + 1 数组的运用啊。
hopewell + 1 + 1 + 1 精彩帖子
pobel + 5 + 5 + 5 精彩帖子

总评分: 经验 + 100  学术水平 + 12  热心指数 + 12  信用等级 + 12   查看全部评分

报纸
pobel 在职认证  发表于 2013-1-28 08:52:35
data test;
    infile cards missover;
    input id $ Type $ Quantity  Price : dollar12.2  Cost : dollar12.2 ;
        format price cost dollar12.2;
        cards;
1 Buy 100  $1.20  $120.00
1 Buy 50  $1.60  $80.00
1 Sell 120
1 Sell 12
1 Buy 15  $1.10  $16.50
1 Buy 40  $1.20 $48.00
1 Sell 70
1 Buy 50  $1.15  $57.50
1 Sell 30
1 Sell 10
2 Buy 100  $1.20
2 Sell 70
2 Buy 50 $1.15
2 Sell 30&iexcl;&iexcl;
2 Sell 10
;

data test1;
   set test(keep=id type quantity);
   where type="Sell";
   by id;
   q_out=quantity;
   do while (q_out>0);
      if q_in<=0 or first.id then set test(where=(_type="Buy") rename=(id=_id quantity=q_in type=_type));
              if id=_id;
          if q_out>q_in then do;
                          cost1=sum(cost1,price*q_in);
                         q_out=q_out-q_in;
                         q_in=0;
                end;
          else do;
                 cost1=sum(cost1,price*q_out);
                 q_in=q_in-q_out;
                 q_out=0;
                 p_in=price;
          end;
   end;
run;

     
data wanted;
    set test;
        if type="Sell" then do;
                set test1 (keep= type cost1);
               cost=cost1;
        end;
        drop cost1;
run;
已有 3 人评分经验 学术水平 热心指数 信用等级 收起 理由
denver + 100 + 5 + 5 + 5 学习了,谢谢
webgu + 1 + 1 + 1 精彩帖子
hopewell + 1 + 1 + 1 精彩帖子

总评分: 经验 + 100  学术水平 + 7  热心指数 + 7  信用等级 + 7   查看全部评分

和谐拯救危机

地板
chenys625 发表于 2013-1-28 09:59:35
我也写了个程序~
data table;
input type $ quantity price;
CARDS;
Buy 100 1.2
Buy 50 1.6
Sell 120 .
Sell 12 .
Buy 15 1.1
Buy 40 1.2
Sell 70 .
Buy 50 1.15
Sell 30 .
Sell 10 .
;
RUN;

data table;
set table;
if type='Buy' then cost=price*quantity;
n=_n_;
run;

data buy_surplus sell;
set table;
if type='Buy' then output buy_surplus;
else output sell;
run;

%macro sell_cost(quantity,n);
data buy_surplus;
set buy_surplus;
sum_quantity+quantity;
sum_cost+cost;
if sum_quantity>=&quantity. and lag(sum_quantity)<&quantity. then do;
quantity=sum_quantity-&quantity.;
cost=price*quantity;
sellcost=sum_cost-price*quantity;
call symput("sellcost_&n.",sellcost);
end;
if sum_quantity>&quantity.;
drop sum_quantity sum_cost sellcost;
run;

data table;
set table;
if n=&n. then cost=&&sellcost_&n.;
run;
%mend sell_cost;

data test;
set sell;
macro=cats('%sell_cost(',quantity,',',n,');');
call execute(macro);
run;
已有 1 人评分经验 学术水平 热心指数 信用等级 收起 理由
denver + 100 + 5 + 5 + 5 都是牛人

总评分: 经验 + 100  学术水平 + 5  热心指数 + 5  信用等级 + 5   查看全部评分

7
denver 发表于 2013-1-28 10:41:31
pobel 发表于 2013-1-28 08:52
data test;
    infile cards missover;
    input id $ Type $ Quantity  Price : dollar12.2  Cost : d ...
兄弟,从你的代码中我学到了很多避免使用loop的技巧,真是感谢了
Denver大家一起读Paper系列索引贴:
https://bbs.pinggu.org/thread-1430892-1-1.html

8
tangliang0905 发表于 2013-1-28 11:00:58
pobel 发表于 2013-1-28 08:52
data test;
    infile cards missover;
    input id $ Type $ Quantity  Price : dollar12.2  Cost : d ...
想到如果是LIFO的方法就会比较复杂一点,
LIFO是LAST IN FIRST OUT, 就这个例子来说,第三个观测120个sell会先sell观测2中的50个,然后再sell观测1中的70个,这样cost就是1.6*50+1.2*70=164,有哪位大牛可以来尝试一下

9
denver 发表于 2013-1-28 11:19:03
tangliang0905 发表于 2013-1-28 11:00
想到如果是LIFO的方法就会比较复杂一点,
LIFO是LAST IN FIRST OUT, 就这个例子来说,第三个观测120个se ...
嗯,这个问题也有意思
Denver大家一起读Paper系列索引贴:
https://bbs.pinggu.org/thread-1430892-1-1.html

10
pobel 在职认证  发表于 2013-1-28 11:44:46
tangliang0905 发表于 2013-1-28 11:00
想到如果是LIFO的方法就会比较复杂一点,
LIFO是LAST IN FIRST OUT, 就这个例子来说,第三个观测120个se ...
data test;
    infile cards missover;
    input id $ Type $ Quantity  Price : dollar12.2  Cost : dollar12.2 ;
        format price cost dollar12.2;
        cards;
1 Buy 100  $1.20  $120.00
1 Buy 50  $1.60  $80.00
1 Sell 120
1 Sell 12
1 Buy 15  $1.10  $16.50
1 Buy 40  $1.20 $48.00
1 Sell 70
1 Buy 50  $1.15  $57.50
1 Sell 30
1 Sell 10
1 Sell 13
2 Buy 100  $1.20
2 Sell 70
2 Buy 50 $1.15
2 Sell 30
2 Sell 10
;

data test1;
    *** Declare the Hash object;
    if 0 then set test(keep=id);
        if _n_=1 then do;
            declare hash stack();
                        stack.definekey("id","_n");
                       stack.definedata("id","_n","q_in","p_in");
                       stack.definedone();
        end;

        set test;
        by id;

        if first.id then _n=0;

        *** Put the "Buy" records into the stack;
        if type="Buy" then do;
               _n+1;
               q_in=quantity;
               p_in=price;
               rc=stack.add();
               output;
        end;

        *** Last in, first out;
        else if type="Sell" then do;
                       q_out=quantity;
                 do while(q_out>0);
                        rc=stack.find();
                       if q_out>=q_in then do;
                             cost1=sum(cost1,p_in*q_in);
                             q_out=q_out-q_in;
                             rc=stack.remove();
                              _n+(-1);
                       end;
                       else do;
                             cost1=sum(cost1,p_in*q_out);
                             q_in=q_in-q_out;
                             rc=stack.replace();
                             q_out=0;
                       end;
                 end;
                output;
        end;
        keep id type quantity price cost cost1;
run;

                  
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
webgu + 3 + 3 + 3 精彩帖子

总评分: 学术水平 + 3  热心指数 + 3  信用等级 + 3   查看全部评分

和谐拯救危机

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-1-5 01:44