Page 2 of 2 [ 28 posts ]  Go to page Previous  1, 2

lau
Veteran
Veteran

User avatar

Joined: 17 Jun 2006
Age: 75
Gender: Male
Posts: 9,619
Location: Somerset UK

28 Mar 2007, 3:07 am

Code:
// project created on 3/28/2007 at 9:05 AM
using System;

namespace WrongPlanet
{
   class MainClass
   {
      public static void Main(string[] args)
      {
         Console.WriteLine("Hello Glib!\n" +
             "No... that would be at least me too!");
      }
   }
}


_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer


Gilb
Veteran
Veteran

User avatar

Joined: 4 Jan 2007
Gender: Male
Posts: 1,214

28 Mar 2007, 12:37 pm

Gilb wrote:
using System;
using System.Collections.Generic;
using System.Text;

namespace program
{
class programme_
{
Static Void Main(string[] args)
{
console.writeline("Hello all you C# programmers out there");
console.writeline("oh that is no one lol");
console.readline();
}
}
}

corrected
[hr]
using System;
using System.Collections.Generic;
using System.Text;

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
int answer = 1;
string input;
int integer;
bool exit = false;
while (exit == false)
{
answer = 1;
Console.WriteLine("enter an integer value (or -1 to exit):");
input = Console.ReadLine();
if (input == "-1")
exit = true;
else
{
try
{
integer = int.Parse(input);
if (integer == 0)
Console.WriteLine("0 factorial is 1");
if (integer < 0)
Console.WriteLine("invalid entry");
if (integer == 1)
Console.WriteLine("the answer is :1");
else
{
while (integer != 1)
{
answer *= integer;
integer--;

// Console.WriteLine("the answer is :{0}", answer.ToString());
}
Console.WriteLine("the answer is :{0}", answer.ToString());
}

}
catch
{
Console.WriteLine("invalid entery");
}
}
}
}
}
}



lau
Veteran
Veteran

User avatar

Joined: 17 Jun 2006
Age: 75
Gender: Male
Posts: 9,619
Location: Somerset UK

28 Mar 2007, 5:42 pm

Gosh Glib. What a program.

Bugs:
Gives no indication that the calculation fails for values greater than 12 (integer overflow).
Goes into infinite loop at EOF on the input stream.
Goes into a rather large loop (2^32) on input of zero ("else" missing)

Cosmetics:
System.Text is not used
System.Collections.Generic is not used (not even available with Mono!)
all "using" statements present twice
in the catch, "entery" instead of "entry".

Style:
No layout (which would have highlighted the bug with input=0).
Treating 0 as a special case is silly (change to "while (integer > 0)").
Should not treat negatives other than "-1" as "special" error... just do 'throw new Exception("input < -1")'
variables defined outside the loop, when they should be inside. (data hiding).
stilted boolean "exit" flag - messy. If it's a complex test to get out of a loop, consider using a "throw"/"catch". If not, stick to simple "while (true)" and "break".

Meaning:
I'd prefer to use "double" data types, and Stirling's formula for a much more complete solution, showing negative integer values as results that are properly "<+/-infinity>".

With most of the changes I consider necessary :) , plus using "ulong" so it will work up to factorial 20:

Code:
using System;

namespace ConsoleApplication3
{
class Program
   {
   static void Main(string[] args)
      {
      while (true)
         {
         Console.WriteLine("enter an integer value (or -1 to exit):");
         string input = Console.ReadLine();
         if (input == null || input == "-1") break;
         try
            {
            ulong answer = 1;
            uint integer = uint.Parse(input);
            while (integer > 1)
               {
               ulong prev = answer;
               answer *= integer;
               if (answer/integer != prev) throw new Exception("overflow");
               integer--;
               }
            Console.WriteLine("the answer is " + answer);
            }
         catch
            {
            Console.WriteLine("invalid entry");
            }
         }
      }
   }
}


_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer


Gilb
Veteran
Veteran

User avatar

Joined: 4 Jan 2007
Gender: Male
Posts: 1,214

29 Mar 2007, 12:47 pm

i am new to programming, thanks for the constructive criticism
i haven't even completed a tutorial



lau
Veteran
Veteran

User avatar

Joined: 17 Jun 2006
Age: 75
Gender: Male
Posts: 9,619
Location: Somerset UK

29 Mar 2007, 6:34 pm

Glib, excellent work then! If you're using Windows, I recommend SharpDevelop. It's now pretty much ported to Linux as well, as MonoDevelop. Both are free and open source.

On thinking about my previous bubbling, having redundant "using" clauses isn't a big sin. I usually finish up with a few. I try to remember, last thing, to go down the list, commenting them all out (bar for maybe the obvious ones I know I need). The error messages quickly sort out which you did, after all, need. I do the same with the equivalent "include" files in other languages.

I have slightly unorthodox views on program layout/whitespace. The rules I stick with are:

  1. Break any rule when it makes the program easier to understand.
  2. Generally, don't comment any individual lines of code, unless you've done something particularly "clever".
  3. Add comments profusely, in blocks. Say why you wrote the code. Say what you think was the point in doing it this particular way. Bear in mind that the person who is quite likely to read the comments is you, a year later. Don't delete any comments.
  4. Routines should, ideally, fit onto one screen. Say 30 lines?
  5. Don't spread out a routine pointlessly. Extra blank lines, no, usually. Braces (or whatever) all on lines by themselves - almost stupid. One statement per line - not good (except when debugging!).
  6. If there's a "prettifier", use it, but feel free to override its defaults whenever you like.

One thing in C, C++ and C# is the choice of line (//) or block (/* */) comments. I have a pet hate of the use of the latter, in general, and especially when uses to produce "box" comments. I feel it works well as a line with "/*" on it, a bunch of free format text, and a final line with the "*/" on it. Most other uses annoy me.
Code:
if (x = y)
        {
        printf("Equal\n");      /********************************
        }                       *                               *
else                            * Clever programmer, aren't I?  *
        {                       *                               *
        printf("Unequal\n");    ********************************/
        }

The above snippet of "C" code (with some more code wrapped round it to make it make sense) will give a warning (in gcc at least), because the first line probably was intended to read as "x == y", not "x = y". I regularly use the latter (assignment and test for zero), and gcc is happy if I put an extra pair of parentheses around it, to show I really meant it.
However, it has what is almost certainly a bug, totally obscured by the "pretty" comment.
I've seen this done in practice, and it's a real pain to see where the bug is.
What I suspect the code was meant to do, I might write as:
Code:
printf(x == y ? "Equal\n" : "Unequal\n");
or
Code:
printf("%squal\n", x == Y ? "E" : "Une");

If a language has features, use them. Some people seem to want to deny the existence of the "?:" triadic operator. They also pretend that C doesn't have macros. Etc. I miss macros in C#, but it compensates in other ways.


_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer


ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

02 Apr 2007, 6:30 pm

It's not short, but I did this for fun.

complex.h

Code:
#ifndef _COMPLEX_H_
#define _COMPLEX_H_
#include <iostream>
#include <cmath>

using std::ostream;
using std::endl;
using std::cin;
using std::cout;

class Complex
{
   friend ostream& operator<<(ostream& out, Complex cxIn);
private:
   double m_fReal;
   double m_fImag;
   int m_nPol;
public:
   Complex();
   double OnGetReal();
   double OnGetImag();
   double OnGetMagn();
   double OnGetAngl();
   void OnPolSet(float fMag, float fAng);
   void OnCarSet(float fReal, float fImag);
   void OnPolSet();
   void OnCarSet();
   Complex operator+(Complex cxC2);
   Complex operator-(Complex cxC2);
   Complex operator*(Complex cxC2);
   Complex operator/(Complex& cxC2);
   Complex OnConj();
};

ostream& operator<<(ostream& out, Complex cxIn);

#endif


complex.cpp
Code:
#include "complex.h"

Complex::Complex()
{
   this->m_fImag=0.0;
   this->m_fReal=0.0;
   this->m_nPol=false;
}
double Complex::OnGetReal()
{
   return this->m_fReal;
}
double Complex::OnGetImag()
{
   return this->m_fImag;
}
double Complex::OnGetMagn()
{
   return sqrt(pow(this->m_fReal,2.0)+pow(this->m_fImag,2.0));
}
double Complex::OnGetAngl()
{
   return atan2(this->m_fImag,this->m_fReal);
}
void Complex::OnPolSet(float fMag, float fAng)
{
   this->m_fReal=fMag*cos(fAng);
   this->m_fImag=fMag*sin(fAng);
   this->m_nPol=true;
}
void Complex::OnCarSet(float fReal, float fImag)
{
   this->m_fReal=fReal;
   this->m_fImag=fImag;
   this->m_nPol=false;
}
void Complex::OnPolSet()
{
   this->m_nPol=true;
}
void Complex::OnCarSet()
{
   this->m_nPol=false;
}
Complex Complex::operator+(Complex cxC2)
{
   Complex cxNew;
   if(this->m_nPol&&cxC2.m_nPol)
      cxNew.m_nPol=true;
   cxNew.m_fImag = this->m_fImag+cxC2.m_fImag;
   cxNew.m_fReal = this->m_fReal+cxC2.m_fReal;
   return cxNew;
}
Complex Complex::operator-(Complex cxC2)
{
   Complex cxNew;
   if(this->m_nPol&&cxC2.m_nPol)
      cxNew.m_nPol=true;
   cxNew.m_fImag = this->m_fImag-cxC2.m_fImag;
   cxNew.m_fReal = this->m_fReal-cxC2.m_fReal;
   return cxNew;
}
Complex Complex::operator*(Complex cxC2)
{
   Complex cxNew;
   if(this->m_nPol&&cxC2.m_nPol)
      cxNew.m_nPol=true;
   cxNew.m_fReal=this->m_fReal*cxC2.m_fReal-this->m_fImag*cxC2.m_fImag;
   cxNew.m_fImag=this->m_fReal*cxC2.m_fImag+this->m_fImag*cxC2.m_fReal;
   return cxNew;
}
Complex Complex::operator/(Complex& cxC2)
{
   Complex cxNew;
   Complex cxTemp1;
   if(this->m_nPol&&cxC2.m_nPol)
      cxNew.m_nPol=true;
   cxNew = (*this)*cxC2.OnConj();
   cxTemp1 = cxC2*cxC2.OnConj();
   cxNew.m_fImag/=cxTemp1.m_fReal;
   cxNew.m_fReal/=cxTemp1.m_fReal;
   return cxNew;
}
Complex Complex::OnConj()
{
   Complex cxConj;
   cxConj.m_fReal=this->m_fReal;
   cxConj.m_fImag=-this->m_fImag;
   cxConj.m_nPol=this->m_nPol;
   return cxConj;
}
ostream& operator<<(ostream& out, Complex cxIn)
{
   static double fPi = 3.14159265358979323846;
   if(!cxIn.m_nPol){
      if(cxIn.OnGetImag() < 0)
         out << cxIn.m_fReal << "-j" << -cxIn.m_fImag;
      else
         out << cxIn.m_fReal << "+j" << cxIn.m_fImag;
   }
   else
   {
      out << cxIn.OnGetMagn() << "<" << cxIn.OnGetAngl()*180.0/fPi << (char)0xF8;
   }
   return out;
}


main.cpp
Code:
#include "complex.h"

void main()
{
   double fReal;
   double fImag;
   Complex cxC1;
   Complex cxC2;
   cout << "Complex Calculator 1.0" << endl << endl;
   cout << "Enter Real#1:";
   cin >> fReal;
   cout << "Enter Imaginary#1:";
   cin >> fImag;
   cxC1.OnCarSet(fReal, fImag);
   cout << "Enter Real#2:";
   cin >> fReal;
   cout << "Enter Imaginary#2:";
   cin >> fImag;
   cxC2.OnCarSet(fReal, fImag);
   cxC1.OnPolSet();
   cxC2.OnPolSet();
   cout << "(" << cxC1 << ")*(" << cxC2 << ")=" <<cxC1*cxC2 << endl << endl;
   cout << "(" << cxC1 << ")/(" << cxC2 << ")=" <<cxC1/cxC2 << endl << endl;
   cout << "(" << cxC1 << ")+(" << cxC2 << ")=" <<cxC1+cxC2 << endl << endl;
   cout << "(" << cxC1 << ")-(" << cxC2 << ")=" <<cxC1-cxC2 << endl << endl;
   cxC1.OnCarSet();
   cxC2.OnCarSet();
   cout << "(" << cxC1 << ")*(" << cxC2 << ")=" <<cxC1*cxC2 << endl << endl;
   cout << "(" << cxC1 << ")/(" << cxC2 << ")=" <<cxC1/cxC2 << endl << endl;
   cout << "(" << cxC1 << ")+(" << cxC2 << ")=" <<cxC1+cxC2 << endl << endl;
   cout << "(" << cxC1 << ")-(" << cxC2 << ")=" <<cxC1-cxC2 << endl << endl;
   system("pause");
}



lau
Veteran
Veteran

User avatar

Joined: 17 Jun 2006
Age: 75
Gender: Male
Posts: 9,619
Location: Somerset UK

02 Apr 2007, 7:55 pm

Yes. Just as I already knew... C++ is so long-winded. :)

I actually don't like the idea of holding a flag for cartesian/polar. It doesn't do anything for you, except make life complicated for no gain.

My little set of classes include basically, Direction, Cartesian and Polar.

Direction is just a class that wraps up a double used for a unique single rotation. I.e it will hold just -Pi to +Pi, not include one end (I forget which I exclude.. I think C# likes to keep +Pi, but personally, I usually prefer -Pi.)

Cartesian is the obvious one, with (Re, Im), and does all the work.

Polar is genuinely different. It holds (R, Theta), with Theta a "Direction". It usually calls on Cartesian to do calculations, but some things it does directly.

My definitions for Cartesian addition go like:

Code:
public static Cartesian operator +(Cartesian C, double v)
{
   return new Cartesian(C.Re + v, C.Im);
}
public static Cartesian operator +(double v, Cartesian C)
{
   return new Cartesian(C.Re + v, C.Im);
}
public static Cartesian operator +(Cartesian P, Cartesian Q)
{
   return new Cartesian(P.Re + Q.Re, P.Im + Q.Im);
}

I choose to define all three, because I like efficient code.

Another bit:
Code:
public double R
{
   get
   {
      double aRe = Math.Abs(Re);
      double aIm = Math.Abs(Im);
      if (aRe > aIm)
      {
         double aImOverRe = aIm/aRe;
         return aRe*Math.Sqrt(1 + aImOverRe*aImOverRe);
      }
      else if (aIm > 0)
      {
         double aReOverIm = aRe/aIm;
         return aIm*Math.Sqrt(1 + aReOverIm*aReOverIm);
      }
      else return 0;
   }
}

I decided not to post the whole shebang:
Code:
  360  1115  8207 Cartesian.cs
  180   556  4168 Direction.cs
  217   696  4883 Polar.cs
  757  2367 17258 total

It's got a fair amount of comments, does some clever footwork (like the above) on various things to preserve maximum precision and handles NaNs sensibly.

If anyone is interested, I'll tidy it up a bit and upload it all to my website.


_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer


ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

03 Apr 2007, 1:35 am

The only difference between polar and cartesian in mine is presentation.

I thought it would be convenient to be able to input polar coordinates so I built a function to do that.



Aspie_Chav
Veteran
Veteran

User avatar

Joined: 6 Feb 2006
Age: 50
Gender: Male
Posts: 2,931
Location: Croydon

03 Apr 2007, 2:43 am

Gilb wrote:
using system.windows.console;

Main()
{
console.writeline("Hello all you C# programmers out there");
console.writeline("oh that is no one lol");
console.readline();
}


Print "Hello all you C# programmers out there"
Print "oh that is no one lol"
readline



lau
Veteran
Veteran

User avatar

Joined: 17 Jun 2006
Age: 75
Gender: Male
Posts: 9,619
Location: Somerset UK

03 Apr 2007, 6:11 pm

ahayes wrote:
The only difference between polar and cartesian in mine is presentation.

I thought it would be convenient to be able to input polar coordinates so I built a function to do that.

I think I didn't say it all properly...

I actually spent a lot of time, messing about with complex number representations, entirely for my own benefit. I was producing a program to display/manipulated some finicky mathematical stuff. Nothing around did the sort of things I wanted.

To make the stuff work in the most convenient fashion, some of it wanted polar coordinates, some cartesian. However, it was always clear when it wanted which.

I did go through a stage with a combined cartesian/polar representation... one that literally held the value represented one way or the other, with the addition of a second flag that showed if the alternate format had been filled in, so it didn't convert between formats more than the once.

However, I eventually decided that it just wasn't the "right" way to do it.

And... With my stuff, if I really want, I can just store either type in an object and test the object type to see if it holds polar or cartesian at the moment. As it happens, I never found the need to do that.

Also, bear in mind that cartesian and polar are just the two most popular ways to store complex numbers.

Anyway. Practice versus theory. Thus I conclude my case, m'lud. :)


_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer


ahayes
Veteran
Veteran

User avatar

Joined: 2 Dec 2006
Gender: Male
Posts: 9,506

03 Apr 2007, 11:16 pm

for what I do it's useful to have both

notice I do j*n and not n*i?



lau
Veteran
Veteran

User avatar

Joined: 17 Jun 2006
Age: 75
Gender: Male
Posts: 9,619
Location: Somerset UK

05 Apr 2007, 6:32 am

ahayes wrote:
for what I do it's useful to have both

notice I do j*n and not n*i?
    Yes... which shows:
  1. You are an engineer, as you use "j" instead of "i". I actually approve of this, but don't do it. :)
  2. You like putting an asterisk in, but I begrudge the extra character.
  3. By using the asterisk, you avoid the syntactic ambiguity which forces me to put my "i" after the number.
  4. You don't begrudge the extra fiddle of moving the sign of a non-zero imaginary part.
I prefer to do:
Code:
Re.ToString() + (Im == 0 ? "" : (Im < 0 ? "" : '+') + Im.ToString() + "i")

Actually, in practice, I do:
Code:
public string ToString(string format)
{
        string R = Re.ToString(format);
        string I = Im.ToString(format);
        if (I != "0") {
                if (!I.StartsWith("-")) R += "+";
                R += I + "i";
        }
        return R; 
}

public override string ToString()
{
        return ToString("");
}


_________________
"Striking up conversations with strangers is an autistic person's version of extreme sports." Kamran Nazeer