求一个用c++编写的时钟程序的源代码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求一个用c++编写的时钟程序的源代码相关的知识,希望对你有一定的参考价值。

要求有指针的界面以及报时功能

参考技术A /*******************************/
/* 时钟源程序 */
/* 仿WINDOWS界面设计 */
/* Turboc3下调试通过 */
/* 包含两个源文件: */
/* clock.cpp win.cpp */
/*******************************/
#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include"time.h"
#include"string.h"
#include"math.h"
#include"dos.h"
#include"bios.h"
#include"win.cpp" //调用窗体显示
#define TRUE 1
#define FALSE 0
#define PI 3.1415926
void cursor(int x,int y) //光标

int count=0;
while(count<=10)
delay(20);
count++;
if(count<=5)
setcolor(9);
else
setcolor(7);
line(x,y,x,y+12);
line(x+1,y,x+1,y+12);


int keyscancode() //检测按键

int key;
while(bioskey(1)==0) return 0;
key=bioskey(0);
key=key&0xff ? key&0xff:key;
return(key);

void message(int x,int y,int n) //状态栏信息

char *msg[6]="Press ESC to quit clock.",
"Press T or t to set time.",
"Press D or d to set date.",
"Press ESC to cancel set.",
"Press Enter to confirm set.",
"Press BackSpace to delete a number.";
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(x,y,x+50*8,y+12);
setcolor(10);
outtextxy(x,y+2,msg[n]);


class CLOCK:public WIN //定义CLOCK为WIN的继承类

int hour,min,sec;
int year,mon,day;
int x,y,radio;
float ak,aj,ai;
int xs,ys,xm,ym,xh,yh;
public:
CLOCK(char *,int,int,int,int);
int isleapyear(int);
int isweek(int,int);
void showclock();
void runclock();
void setclock();
void inittodaydate();
void initnowtime();
void showdate();
void hidedate();
void pip();
void showtime();
void setdates();
;
//构造函数
CLOCK::CLOCK(char *n,int a,int b,int c,int d):WIN(n,a,b,c,d)
x=a+130;
y=b+155;
radio=120;

int CLOCK::isleapyear(int year) //判断是否闰年

if(year%100!=0&&year%4==0)
return TRUE;
if(year%400==0)
return TRUE;
return FALSE;

int CLOCK::isweek(int year,int mon) //计算year年mon月1号的星期数

int days=0,week=0;
int month[12]=31,28,31,30,31,30,31,31,30,31,30,31;
if(isleapyear(year)) month[1]=29;
else month[1]=28;
for(int i=1;i<year;i++)

days=365;
if(isleapyear(i)) days=366;
week=(days+week)%7;

for(i=0;i<mon-1;i++)
week=(month[i]+week)%7;
return week;

void CLOCK::setdates() //设置曰期

struct date set;
int key=0,count=0,index=0;
int textx=x+140,texty=y+42,tcnt=0;
char text[2];
int dateset[10];
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(textx,texty,textx+150,texty+12);
do
message(80+6,380-12,index+3);
count++;
index=count/10;
if(count==29) count=0;
runclock();
key=keyscancode();
cursor(textx,texty);
if((key>='0'&&key<='9')&&tcnt!=10)
//限制按键,防止误操作
if(tcnt<4||(tcnt==5&&key<='1')||((tcnt==6&&dateset[tcnt-1]==1&&key<='2')||(tcnt==6&&dateset[tcnt-1]==0))||(tcnt==8&&key<='3')||(tcnt==9))

sprintf(text,"%c",key);
text[1]='\0';
setcolor(LIGHTBLUE);
outtextxy(textx,texty+2,text);
dateset[tcnt]=key-'0';
textx+=10;
tcnt++;
if((tcnt==4||tcnt==7)&tcnt!=10)
outtextxy(textx,texty+2,"-");
textx+=10;
tcnt++;



if(key==8&&tcnt>0)
if(tcnt==5||tcnt==8)

tcnt-=2;
textx-=20;

else
tcnt--;
textx-=10;
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(textx,texty,textx+8,texty+12);

while(key!=13&&key!=27);
if(key==27) return; //如果是ESC键,则退出设置
if(key==13) //如果ENTER键,则设置曰期

set.da_year=dateset[0]*1000+dateset[1]*100+dateset[2]*10+dateset[3];
set.da_mon=dateset[5]*10+dateset[6];
set.da_day=dateset[8]*10+dateset[9];
setdate(&set);


void CLOCK::setclock() //设置时间

struct time set;
int key=0,count=0,index=0;
int textx=x+140,texty=y+6,tcnt=0;
char text[2];
int timeset[8];
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(textx,texty,textx+150,texty+12);
do
message(80+6,380-12,index+3);
count++;
index=count/10;
if(count==29) count=0;
key=keyscancode();
cursor(textx,texty);
if((key>='0'&&key<='9')&&tcnt!=8)
//限制按键,防止误操作
if((tcnt==0&&key<='2')||((tcnt==1&&key<='3'&×et[tcnt-1]==2)||(tcnt==1&×et[tcnt-1]!=2))||(tcnt==3&&key<='5')||(tcnt==6&&key<='5')||tcnt==4||tcnt==7)

sprintf(text,"%c",key);
text[1]='\0';
setcolor(9);
outtextxy(textx,texty+2,text);
timeset[tcnt]=key-'0';
textx+=10;
tcnt++;
if((tcnt==2||tcnt==5)&&tcnt!=8)
outtextxy(textx,texty+2,":");
textx+=10;
tcnt++;



if(key==8&&tcnt>0)
if(tcnt==3||tcnt==6)
tcnt-=2;
textx-=20;

else
tcnt--;
textx-=10;

setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(textx,texty,textx+8,texty+12);

while(key!=13&&key!=27);
if(key==27) return;
if(key==13)

set.ti_hour=timeset[0]*10+timeset[1];
set.ti_min=timeset[3]*10+timeset[4];
set.ti_sec=timeset[6]*10+timeset[7];
settime(&set);


void CLOCK::showdate() //在窗体上显示曰期

char nowdate[15];
char days[4];
char *week[7]="Sun","Mon","Tue","Wed","Thu","Fri","Sat";
int month[12]=31,28,31,30,31,30,31,31,30,31,30,31;
int dayx=x+135,dayy=y-88,todayweek=0,control;
struct date d;
getdate(&d);
setcolor(12);
for(int i=0;i<7;i++)
outtextxy(x+i*8*4+135,y-100,week[i]);
todayweek=isweek(d.da_year,d.da_mon); // 得到本月1号的星期数
if(todayweek+1!=7)
for(i=1;i<=todayweek+1;i++) dayx=dayx+4*8;
control=todayweek+1;
if(isleapyear(d.da_year)) month[1]=29;
else month[1]=28;
setcolor(11);
for(i=1;i<=month[d.da_mon-1];i++)

control++;
sprintf(days,"%3d",i);
if(i==d.da_day) setcolor(LIGHTMAGENTA);
outtextxy(dayx,dayy,days);
setcolor(11);
dayx=dayx+4*8;
if(control%7==0) dayx=x+135; dayy=dayy+12;

todayweek=(todayweek+day)%7; //得到今天的星期数
sprintf(nowdate,"%04d-%02d-%02d %s",d.da_year,d.da_mon,d.da_day,week[todayweek]);
nowdate[14]='\0';
setcolor(LIGHTBLUE);
outtextxy(x+185,y-120,nowdate);
if(d.da_year!=year||d.da_mon!=mon||d.da_day!=day) //如果曰期改变了,则先隐藏曰期,再显示
hidedate();

void CLOCK::hidedate() //隐藏曰期

inittodaydate();
setfillstyle(SOLID_FILL,LIGHTGRAY); //抹去曰期,如果曰期改变了
bar(x+135,y-90,x+135+6*8*4+3*8,y-90+12*6);
bar(x+165,y-122,x+170+16*8+10,y-112);

void CLOCK::showtime() //显示时间

char nowtime[9];
sprintf(nowtime,"%02d:%02d:%02d",hour,min,sec);
nowtime[8]='\0';
setcolor(14);
outtextxy(x-30,y+82,nowtime);
ak=(90+30*(12-hour)-min*5/60.*6)*PI/180; //时针角度
aj=(90+6*(60-min))*PI/180; //分针角度
ai=(90+6*(60-sec))*PI/180; //秒针角度
xs=x+cos(ai)*(radio-10);
ys=y-sin(ai)*(radio-10);
xm=x+cos(aj)*(radio-25);
ym=y-sin(aj)*(radio-25);
xh=x+cos(ak)*(radio-45);
yh=y-sin(ak)*(radio-45);
setcolor(RED); //画时针
setlinestyle(0,0,THICK_WIDTH);
line(x-cos(ak)*(radio-118),y+sin(ak)*(radio-118),xh,yh);
setlinestyle(0,0,NORM_WIDTH); //画时针在钟面上指示位置
circle(x+cos(ak)*radio,y-sin(ak)*radio,2);
setcolor(LIGHTGREEN);
circle(x+cos(aj)*radio,y-sin(aj)*radio,2); //画分针在钟面上的指示位置
line(x-cos(aj)*(radio-115),y+sin(aj)*(radio-115),xm,ym); //画分针
setcolor(LIGHTBLUE);
line(x-cos(ai)*(radio-110),y+sin(ai)*(radio-110),xs,ys); //画秒针
circle(x+cos(ai)*radio,y-sin(ai)*radio,2); //画秒针在钟面上的指示位置

void CLOCK::runclock() //运行时钟

int h,m,s;
float ah;
struct time tim;
gettime(&tim);
s=tim.ti_sec;
m=tim.ti_min;
h=tim.ti_hour;
ah=(90+30*(12-h)-m*5/60.*6)*PI/180;
showdate();
showtime();
delay(200);
nosound();
if(ah!=ak)
setcolor(LIGHTGRAY);
setlinestyle(0,0,THICK_WIDTH);
line(x-cos(ak)*(radio-118),y+sin(ak)*(radio-118),xh,yh);
setlinestyle(0,0,NORM_WIDTH);
if(hour%5==0) setcolor(YELLOW);
circle(x+cos(ak)*radio,y-sin(ak)*radio,2);
setcolor(LIGHTGRAY);
hour=h;

if(m!=min)
setcolor(LIGHTGRAY);
line(x-cos(aj)*(radio-115),y+sin(aj)*(radio-115),xm,ym);
if(min%5==0) setcolor(YELLOW);
circle(x+cos(aj)*radio,y-sin(aj)*radio,2);
min=m;

if(s!=sec)
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(x-30,y+80,x-30+8*8,y+80+8);
setcolor(LIGHTGRAY);
if(sec%5==0) setcolor(YELLOW);
circle(x+cos(ai)*radio,y-sin(ai)*radio,2);
setcolor(LIGHTGRAY);
line(x-cos(ai)*(radio-110),y+sin(ai)*(radio-110),xs,ys);
sec=s;
if(hour>=12) //整点报时
h=hour-12;
else
h=hour;
if(min==59&&sec>=60-h)
sound(392);
if(min==00&&sec==00)
sound(784);

showclock();

void CLOCK::inittodaydate() //初始化今天的曰期

struct date initdate;
getdate(&initdate);
year=initdate.da_year;
mon=initdate.da_mon;
day=initdate.da_day;

void CLOCK::initnowtime() //初始化时间

struct time inittime;
gettime(&inittime);
hour=inittime.ti_hour;
min=inittime.ti_min;
sec=inittime.ti_sec;

void CLOCK::showclock() //显示时钟

float alpha;
int x0,y0,i;
char s[3];
for(i=60;i>=1;i--) //显示钟面上数字

alpha=(90+6*(60-i))*PI/180;
x0=x+cos(alpha)*radio;
y0=y-sin(alpha)*radio;
setcolor(14);
if(i%5==0)
circle(x0,y0,2);
sprintf(s,"%d",i/5);
outtextxy(x+cos(alpha)*(radio-10)-4,y-sin(alpha)*(radio-10)-2,s);

else
circle(x0,y0,1);



void about(int x,int y,int index) //关于与帮助信息

int i=0,t=0;
char *abouttext[]="You can get message from",
" the status bar at the ",
"bottom.",
"When you set time,you just",
"input like this:080819.",
"The symbol ':' isn't needed.",
"Set date is the same.",
"This clock is designed by",
" Nie Shiqiu.(C99102-07)",
"I'm very interested in C/C++",
"This is my course design.";
setfillstyle(SOLID_FILL,LIGHTGRAY);
bar(x,y,x+27*8+6,y+4*12);
t=index-3;
if(index<4)
y=y+(3-index)*12;
t=0;

for(i=t;i<=index;i++)

if(i<11)
if(i==8) setcolor(RED); //名字着重显示
else setcolor(LIGHTBLUE);
outtextxy(x+2,y+2,abouttext[i]);

y+=12;


void main() //主程序

int driver=DETECT,mode;
int exitflag=FALSE,key,index=0,count=0,aboutindex=0,acnt=0;
WIN winCLK("Clock",80,80,570,385); //创建窗体
CLOCK c1("Clock",80,80,570,385);
initgraph(&driver,&mode,"");
winCLK.Form(FALSE);
c1.showclock();
c1.initnowtime();
do
about(342,80+185+44,aboutindex);
acnt++;
aboutindex=acnt/10;
if(acnt==139) acnt=0;
message(80+6,380-12,index);
count++;
index=count/10;
if(count==29) count=0;
key=keyscancode();
c1.runclock();
if(key==27) exitflag=TRUE; //按ESC退出
if(key=='T'||key=='t')
c1.showtime();
c1.setclock();

if(key=='D'||key=='d')
c1.setdates();

while(exitflag==FALSE);
winCLK.draw_closebutton(570-18,80+4,BLACK,TRUE);
delay(300);
closegraph();

/*******************/
/* 窗体文件 win.cpp*/
/*******************/
#include"graphics.h"
#define TRUE 1
#define FALSE 0
class WIN

char title[20];
protected:
int left,top,right,bottom;
public:
WIN(char *n,int a,int b,int c,int d)strcpy(title,n);left=a;top=b;right=c;bottom=d;
void draw_minbutton(int left,int top,int color,int state);
void draw_maxbutton(int left,int top,int color,int state);
void draw_closebutton(int left,int top,int color,int state);
void Form(int);
void Button(int,int,int,int,int);
void line3d(int,int,int,int,int);
void Frame(int,int,int,int,char *);
;
void WIN::Frame(int left,int top,int right,int bottom,char *s)

line3d(left,top+2,right,top+2,FALSE);
line3d(left,top+3,left,bottom,FALSE);
line3d(left,bottom,right,bottom,FALSE);
line3d(right,top+2,right,bottom,FALSE);
bar(left+4,top,left+4+8*strlen(s)+4,top+8);
setcolor(10);
outtextxy(left+5,top,s);

void WIN::line3d(int left,int top,int right,int bottom,int state) /*画有凹凸感的线条函数*/

if(state==FALSE)
setcolor(0);
line(left,top,right,bottom);
setcolor(15);
if(top==bottom)
line(left,top+1,right,bottom+1);

if(left==right)
line(left+1,top,right+1,bottom);

else
setcolor(15);
line(left,top,right,bottom);
setcolor(0);
if(top==bottom)
line(left,top+1,right,bottom+1);

if(left==right)
line(left+1,top,right+1,bottom);


void WIN::Form(int state)

Button(left,top,right,bottom,state);
setfillstyle(1,1);
bar(left+2,top+2,right-2,top+20);
setcolor(YELLOW);
circle(left+12,top+12,8);
line(left+12,top+12,left+12,top+4);
line(left+12,top+12,left+16,top+12);
outtextxy(left+16+10,top+8,title);
draw_minbutton(right-16*3-4,top+4,BLACK,FALSE);
draw_maxbutton(right-16*2-3,top+4,BLACK,FALSE);
draw_closebutton(right-18,top+4,BLACK,FALSE);
Frame(left+5,top+25,left+255,top+278,"Time");
Frame(left+260,top+25,right-5,top+25+20*6,"Date");
line3d(left+280,top+25+20,right-25,top+25+20,FALSE);
Frame(left+260,top+150,right-5,top+150+30,"SetTime(T)");
Button(left+265,top+160,right-8,top+150+25,TRUE);
Frame(left+260,top+185,right-5,top+185+30,"SetDate(D)");
Button(left+265,top+195,right-8,top+185+25,TRUE);
Button(left+4,bottom-20,right-4,bottom-4,TRUE);
Frame(left+260,top+185+35,right-5,bottom-27,"About");

void WIN::Button(int left,int top,int right,int bottom,int state)

if(state==-1)
setfillstyle(1,7);
bar(left,top,right,bottom);
setfillstyle(1,7);
bar(left,top,right,bottom);
if(state==FALSE)

setcolor(15);
line(left,top,right,top);
line(left,top,left,bottom);
setcolor(0);
line(left,bottom,right,bottom);
line(right,top,right,bottom);
setcolor(8);
line(left+1,bottom-1,right-1,bottom-1);
line(right-1,top+1,right-1,bottom-1);

if(state==TRUE)

setcolor(8);
line(left,top,right,top);
line(left,top,left,bottom);
setcolor(15);
line(left,bottom,right,bottom);
line(right,top,right,bottom);


void WIN::draw_minbutton(int left,int top,int color,int state)

if(state==FALSE)

Button(left,top,left+15,top+15,FALSE);
setcolor(color);
line(left+3,top+11,left+12,top+11);
line(left+3,top+12,left+12,top+12);

else

Button(left,top,left+15,top+15,TRUE);
setcolor(color);
line(left+3,top+13,left+12,top+13);
line(left+3,top+12,left+12,top+12);


void WIN::draw_maxbutton(int left,int top,int color,int state)


if(state==FALSE)

Button(left,top,left+15,top+15,FALSE);
setcolor(color);
rectangle(left+4,top+4,left+12,top+12);
rectangle(left+4,top+5,left+12,top+12);

else

Button(left,top,left+15,top+15,TRUE);
setcolor(color);
rectangle(left+4,top+4,left+12,top+14);
rectangle(left+4,top+3,left+12,top+14);


void WIN::draw_closebutton(int left,int top,int color,int state)

if(state==FALSE)

Button(left,top,left+15,top+15,FALSE);
setcolor(color);
line(left+4,top+4,left+12,top+12);
line(left+5,top+4,left+13,top+12);
line(left+4,top+12,left+12,top+4);
line(left+5,top+12,left+13,top+4);

else

Button(left,top,left+15,top+15,TRUE);
setcolor(color);
line(left+4,top+4,left+12,top+12);
line(left+5,top+4,left+13,top+12);
line(left+4,top+12,left+12,top+4);
line(left+5,top+12,left+13,top+4);

本回答被提问者采纳

用 C++ 编写性能关键的 C# 代码

【中文标题】用 C++ 编写性能关键的 C# 代码【英文标题】:Writing performance critical C# code in C++ 【发布时间】:2011-04-09 21:06:58 【问题描述】:

我目前正在编写一些性能关键代码,并且我有一种特殊情况,我很想用 C# 编写整个应用程序,但性能原因意味着 C++ 最终要快得多。

我对一些代码的两种不同实现(一个在 C# 中,另一个在 C++ 中)进行了一些基准测试,时间显示 C++ 版本快 8 倍,两个版本都处于发布模式并启用了所有优化。 (其实C#有编译成64位的优势。我忘了在C++的时候启用这个)

所以我想,我可以用 C# 编写大部分代码库(C# 使得编写非常容易),然后在性能至关重要的地方编写本机版本。我在 C# 和 C++ 中测试的特定代码段是花费超过 95% 处理时间的关键领域之一。

但是,在这里编写本机代码的推荐智慧是什么?我从未编写过调用本机 C++ 的 C# 应用程序,所以我不知道该怎么做。我希望以一种尽可能减少进行本机调用的成本的方式来做到这一点。

谢谢!

编辑:下面是我实际尝试处理的大部分代码。这是一个n体模拟。 95-99% 的 CPU 时间将花在 Body.Pairwise() 中。

class Body

    public double Mass;
    public Vector Position;
    public Vector Velocity;
    public Vector Acceleration;

    // snip

    public void Pairwise(Body b)
    
        Vector dr = b.Position - this.Position;
        double r2 = dr.LengthSq();
        double r3i = 1 / (r2 * Math.Sqrt(r2));

        Vector da = r3i * dr;
        this.Acceleration += (b.Mass * da);
        b.Acceleration -= (this.Mass * da);
    

    public void Predict(double dt)
    
        Velocity += (0.5 * dt) * Acceleration;
        Position += dt * Velocity;
    

    public void Correct(double dt)
    
        Velocity += (0.5 * dt) * Acceleration;
        Acceleration.Clear();
    

我还有一个类,它只使用以下方法驱动模拟:

    public static void Pairwise(Body[] b, int n)
    
        for (int i = 0; i < n; i++)
            for (int j = i + 1; j < n; j++)
                b[i].Pairwise(b[j]);
    

    public static void Predict(Body[] b, int n, double dt)
    
        for (int i = 0; i < n; i++)
            b[i].Predict(dt);
    

    public static void Correct(Body[] b, int n, double dt)
    
        for (int i = 0; i < n; i++)
            b[i].Correct(dt);
    

主循环看起来像:

for (int s = 0; s < steps; s++)

    Predict(bodies, n, dt);
    Pairwise(bodies, n);
    Correct(bodies, n, dt);

以上只是我实际正在开发的大型应用程序的最低限度。还有更多的事情发生,但对性能最关键的事情发生在这三个函数中。我知道成对函数很慢(它是 n^2),而且我确实有其他更快的方法(Barnes-hutt 一个,它是 n log n)但这超出了我在此要求的范围问题。

C++ 代码几乎相同:

struct Body

public:
    double Mass;
    Vector Position;
    Vector Velocity;
    Vector Acceleration;

    void Pairwise(Body &b)
    
        Vector dr = b.Position - this->Position;
        double r2 = dr.LengthSq();
        double r3i = 1 / (r2 * sqrt(r2));

        Vector da = r3i * dr;
        this->Acceleration += (b.Mass * da);
        b.Acceleration -= (this->Mass * da);
    

    void Predict(double dt)
    
        Velocity += (0.5 * dt) * Acceleration;
        Position += dt * Velocity;
    

    void Correct(double dt)
    
        Velocity += (0.5 * dt) * Acceleration;
        Acceleration.Clear();
    
;

void Pairwise(Body *b, int n)

    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
            b[i].Pairwise(b[j]);


void Predict(Body *b, int n, double dt)

    for (int i = 0; i < n; i++)
        b[i].Predict(dt);


void Correct(Body *b, int n, double dt)

    for (int i = 0; i < n; i++)
        b[i].Correct(dt);

主循环:

for (int s = 0; s < steps; s++)

    Predict(bodies, n, dt);
    Pairwise(bodies, n);
    Correct(bodies, n, dt);

还有一个 Vector 类,它的工作原理就像一个常规的数学向量,为简洁起见,我不包括在内。

【问题讨论】:

C# 不应该更慢。您可以使用未经检查的块来实现更快的代码,以避免溢出检查和其他东西。 ***.com/questions/5326269/… @Yochai:我已经尝试过,将我所有的算术都包装在不安全的块中。它归结为一些做大量浮点数学的函数,但我每秒都在做大量的计算。另外,我想知道如何从 C# 调用 C++,因为我已经有一些用 C++ 编写的现有代码。我想编写的一些较新的代码与计算无关,但更容易用 C# 编写。 @Yochai:我不太确定未检查代码是否比已检查代码快。虽然我承认我无法解释原因,但我目睹了它一直略微变慢的情况。 @Mike Bantegui,这是一个老问题,但您应该查看 C++ AMP 以进行 N Body 模拟。通过让它在 GPU 硬件上运行,它可以提供更好的性能提升。应该很简单,因为您已经在调用非托管代码。 【参考方案1】:

您需要与本机代码交互。你可以把它放在一个DLL中并pinvoke。好的,当您不经常转换并且界面很薄时。最灵活和最快速的解决方案是用 C++/CLI 语言编写一个 ref 类包装器。看看this magazine article的介绍。

最后但同样重要的是,您确实应该分析 C# 代码。 8 倍是相当多的。在您至少了解为什么它那么慢之前,请不要开始这样做。您不想在 C++ 代码中重现原因,那样会毁掉一周的工作。

并提防错误的直觉。 64 位代码实际上更快,它通常比 x86 代码慢一点。它有一堆额外的寄存器,非常很好。但是所有指针的大小都是双倍的,并且您不会获得双倍的 cpu 缓存。 .

【讨论】:

我重新计时,确保输入数据相同,但仍然慢了 5 倍。有什么我应该注意的事情会很容易降低 C# 的性能吗? 通过简单地重做时序几乎使性能翻倍在我的书中将是一个危险信号。没有用于优化 C# 代码的通用剧本,只有好的分析器可以向您展示周期的去向。对 Debug 构建进行概要分析或附加调试器时存在明显错误。 我认为“两倍快”来自于我跑过 Visual Studio 的事实。对于微小的计算,我可以始终如一地获得 500 毫秒(C#)和 2000 毫秒(C++)的时间。我进行了分析并确认了一种方法,其中所有周期都被花费了,这在两个平台上都是相同的,并且具有相同的 CPU 时间百分比 (99%)。 @Mike Bantegui:汉斯是对的。你必须找出真正发生了什么。当然,当我听到“周期去哪里”和“所有周期都花在哪里”时,我会立即产生怀疑,因为最浪费时间的往往是看似无辜甚至看不见的函数调用,它们伪装自己通过将时间花在其他地方。我会鼓励你沉下心来——在指令级别上一步一步,或者做this。【参考方案2】:

您有两个选择:P/Invoking 和 C++/CLI。

P/调用

通过使用 P/Invoke 或 Platform Invoke,.NET(以及 C#)可以调用非托管代码(您的 C++ 代码)。这可能有点让人不知所措,但绝对有可能让您的 C# 代码调用对性能至关重要的 C++ 代码。

一些 MSDN 链接可帮助您入门:

Consuming Unmanaged DLL Functions Interop Marshaling DllImportAttribute

基本上,您将创建一个 C++ DLL,该 DLL 定义了您想从 C# 调用的所有非托管函数。然后,在 C# 中,您将使用 DllImportAttribute 将该函数导入 C#。

例如,您有一个 C++ 项目,该项目创建了具有以下功能的 Monkey.dll:

extern "C" __declspec(dllexport) void FastMonkey();

然后您将在 C# 中进行如下定义:

class NativeMethods

    [DllImport("Monkey.dll", CallingConvention=CallingConvention.CDecl)]
    public static extern void FastMonkey();

然后您可以通过调用NativeMethods.FastMonkey 在 C# 中调用 C++ 函数。

几个常见的陷阱和注意事项:

花时间学习互操作封送处理。理解这一点将极大地帮助创建正确的 P/Invoking 定义。 默认调用约定为 StdCall,但 C++ 将默认为 CDecl。 默认字符集是 ANSI,因此如果您想编组 Unicode 字符串,则必须更新您的 DllImport 定义(请参阅 MSDN - DllImport.CharSet 文档)。 http://www.pinvoke.net/ 是了解如何 P/Invoke 标准 Windows 函数调用的有用资源。如果您知道类似的 Windows 函数调用,您也可以使用它来了解如何编组某些内容。

C++/CLI

C++/CLI 是 Microsoft 创建的一系列 C++ 扩展,用于使用 C++ 创建 .NET 程序集。 C++/CLI 还允许您将非托管代码和托管代码混合到一个“混合”程序集中。您可以创建一个 C++/CLI 程序集,其中包含您的性能关键代码和您想要的任何围绕它的 .NET 类包装器。

有关 C++/CLI 的更多信息,我建议从 MSDN - Language Features for Targeting the CLR 和 MSDN - Native and .NET Interoperability 开始。

我建议您从 P/Invoking 路线开始。我发现明确区分非托管代码和托管代码有助于简化事情。

【讨论】:

【参考方案3】:

在 C# 中,Vector 是类还是结构?我怀疑这是一个类,而 Arthur Stankevich 的观察结果一针见血,你可能会分配其中的许多。尝试将 Vector 设为结构,或重用相同的 Vector 对象。

【讨论】:

是的,我也在想同样的事情。我多次看到一个 Vector 类型是用 Java 方式实现的,这会导致大量的分配。而在 C++ 中,Vector 的操作大部分可以内联。为了达到与 C++ 相当的性能,Vector 类型应该实现为 struct,并且更喜欢作为操作的 ref 参数传递而不是使用重载的运算符,这样可以更好地通过 jitter 内联。【参考方案4】:

最简单的方法是创建 C++ ActiveX dll。

然后您可以在 C# 项目中引用它们,Visual Studio 将创建将包装 ActiveX COM 对象的互操作。

您可以像 C# 代码一样使用互操作代码,无需额外的包装代码。

有关 AciveX/C# 的更多信息:

Create and Use a C++ ActiveX component within a .NET environment

【讨论】:

这是最有效的方法吗?或者 P/Invoke 会更有效吗?我不介意一种方法更难,只要这意味着我可以提取尽可能多的性能。 这很容易做到。我认为通信开销没有区别。【参考方案5】:

“我在两个方面做了一些基准测试 一些代码的不同实现 (一个在 C# 中,另一个在 C++ 中)和 时序显示 C++ 版本 快了 8 倍”

我用 C#、C++、Java 和一点 F# 做了一些数值计算,C# 和 C++ 之间的最大差异是 3.5。

分析你的 C# 版本并找到瓶颈(可能存在一些与 IO 相关的问题,不必要的分配)

【讨论】:

没有 IO 瓶颈(除了加载测试数据之外没有实际的 IO),我重新检查了代码,我可以确认有一种方法(在 C# 和 C++ 上)除了原始之外什么都不做计算,并且占用了 99% 的时间。 当然,我可以发布已知昂贵的特定部分。这只不过是一个重力模拟。给我几分钟,我会更新我的主要帖子。【参考方案6】:

对于简单的情况,P/Invoke 绝对比 COM Interop 更容易。但是,如果您在 C++ 中执行更大的类模型块,您可能真的需要考虑 C++/CLI 或 COM 互操作。

ATL 使您可以立即创建一个类,并且一旦对象被实例化,调用开销基本上与 P/Invoke 一样小(除非您使用动态调度,IDispatch,但这应该很明显)。

当然,C++/CLI 是最好的选择,但这并不适用于所有地方。 P/Invoke 可以在任何地方工作。 COM 互操作是supported on Mono up to degree

【讨论】:

【参考方案7】:

看起来您在代码中做了很多隐式 Vector 类分配:

Vector dr = b.Position - this.Position;
...
Vector da = r3i * dr;
this.Acceleration += (b.Mass * da);
b.Acceleration -= (this.Mass * da);

尝试重用已分配的内存。

【讨论】:

以上是关于求一个用c++编写的时钟程序的源代码的主要内容,如果未能解决你的问题,请参考以下文章

用java编写的时钟程序

求帮忙写个程序 JAVA C++都行

求做一个C++程序 求四个数中的最大数和最小数差值.要求用函数实现该功能.

求一个用verilog实现二分之一分频(是提高频率,不是降低频率)的代码

求一个用C语言编写的小游戏代码

c语言怎么样编写一个时钟程序