I have made a simple class which represents a point on the Cartesian plane - the Position class, which isn't working properly. As I increment the decimal coordinates, the integer coordinates don't seem to respond. That is what the ConsolidatePosition() method is for. It seems that any Double type numbers that are passed to the MoveRelative() method are converted to an integer before being stored in a *PosPrecise, as if they had already been processed by Convert.ToInt32() (the conversion seems to follow the 'round x.5 to nearest even' rule).
My code uses literal arguments, if that makes a difference. eg. MoveRelative(0, 0.5) appears in the code.
public class Position{
public int XPos;
public int YPos;
public double XPosPrecise;
public double YPosPrecise;
public class Position{
public int XPos;
public int YPos;
public double XPosPrecise;
public double YPosPrecise;
public Position(){
XPosPrecise = 0;
YPosPrecise = 0;
ConsolidatePosition();
}
public Position(double x, double y){
XPosPrecise = x;
YPosPrecise = y;
ConsolidatePosition();
}
public void MoveRelative(double x, double y){
XPosPrecise += x;
YPosPrecise += y;
ConsolidatePosition();
}
public void MoveAbsolute(double x, double y){
XPosPrecise = x;
YPosPrecise = y;
ConsolidatePosition();
}
private void ConsolidatePosition(){
XPos = Convert.ToInt32(XPosPrecise);
YPos = Convert.ToInt32(YPosPrecise);
}
}
And here are some calls to the code. They are the only calls made for one instance of the class. They are called every 'frame' of my program. I have tested the Move() method with whole and near-whole numbers, and the phantom rounding still occurs. As it stands, the output doesn't change after many calls of Move().
public void RotateRight(){
// apply central positioning
switch(ActorDirection){
case 0:
ActorPosition.MoveRelative(-2, 1);
break;
case 1:
ActorPosition.MoveRelative(2, -2);
break;
case 2:
ActorPosition.MoveRelative(-1, 2);
break;
case 3:
ActorPosition.MoveRelative(1, -1);
break;
}
ActorSprite.RotateRight(true);
ActorDirection = (ActorDirection + 1) % 4;
}
public void Move(int direction){
while(ActorDirection != direction){
RotateRight();
}
switch (ActorDirection % 4){
case 0:
ActorPosition.MoveRelative(0, -0.5);
break;
case 1:
ActorPosition.MoveRelative(0.5, 0);
break;
case 2:
ActorPosition.MoveRelative(0, 0.5);
break;
case 3:
ActorPosition.MoveRelative(-0.5, 0);
break;
}
}
My question is, am I missing an implicit conversion here?
(This is written and compiled in C#)
My guess would be the rounding of the decimal values when converted to integers is causing the problem here (as in it's a usage problem). (double)0.99 converts to (int)0. Perhaps you're looking for Math.Round()?
SORRY ALL. The problem was that a screen-wrap function returns a new position object with integer precision, not decimal precision. This was being called every game step, and replaced the old Position object, never allowing the *PosPrecise to reach more than 0.5. When the function result was set to my object, it reset to 0. It wasn't an error in any of the above code, and Payo was correct, it was how I was using it.
Related
I created a validation function as below:
public static T getAsDigit<T>( this Textbox tb, float min, float max ){
}
Most of the time, the validation range is specificed in integers. It works fine. But when I try to pass in decimals, it give me error sth like can't convert double to float, I have to change defination to double.
I am new to C#, how can I pass in the digits as float ? without doing sth unintuitive like Convert.toFloat('1.3').
My use case only requires 3 decimal place precision, value range 0.000 ~ 10.000. Is there any disadvantage in using float versus double in C#? Since I used and saw people use float a lot in sql when decimal() is optional.
Use f literal: getAsDigit(1.34f)
Or cast value to float getAsDigit((float)1.34)
You have to convert the double to flow so i recommend you do
float.Parse(x)
the cleaner option would be to create a new var and convert it to float there instead of in the injection so something like this:
double x = 1.3;
var newFloat = float.Parse(x);
I think you want to write a validation for the value of the TextBox.
You can upgrade your method to make it generic for all value type struct
public static T getAsDigit<T>(this TextBox tb, T min, T max) where T : struct, IComparable<T>
{
var valueConverted = default(T);
try
{
valueConverted = (T)Convert.ChangeType(tb.Text, typeof(T));
}
catch(Exception e)
{
//do something you want, rethown i.e
}
if (valueConverted.CompareTo(max) > 0)
return max;
if (valueConverted.CompareTo(min) < 0)
return min;
return valueConverted;
}
And you can simply pass the type you want.
string a = "10.5"; // suppose that a is TextBox.Text
var b = a.getAsDigit<float>(10,11); // return 10.5f
var c = a.getAsDigit<decimal>(11,12); //return 11d
var d = a.getAsDigit<double>(9,10); //return 10d
Assume we have a huge list of numeric cartesian coordinates (5;3)(1;-9) etc. To represent a point in oop I created a struct/object (c#):
public struct Point
{
public int X, Y { get; }
public Point(int x, int y)
{
// Check if x,y falls within certain boundaries (ex. -1000, 1000)
}
}
It might be wrong of how I am using struct. I guess normally you would not use a constructor but this is not the point.
Suppose I want to add a list of 1000 points and there is no guarantee that these coordinates fall within boundaries. Simply if the point is not valid, move to the next one without failing and inform user about it. As for object, I would think that Point should be responsible for instantiation and validation by itself but I am not sure how to deal with it in this particular case. Checking x, y beforehand by the caller would be the simplest approach but it does not feel right because caller would have to handle logic that should reside in Point.
What would the most appropriate approach to validate and handle incorrect coordinates without failing and violating SRP?
You can't do this in the constructor; the constructor either runs succesfully or it doesn't. If it doesn't its because an exception is raised, so, so much for silently failing. You could catch exceptions but that woul basically mean you are using exceptions as a control flow mechanism and that is a big no no, don't do that!
One solution similar to what you are thinking is to use a static factory method:
public struct Point
{
public static bool TryCreatePoint(int x, int y, Bounds bounds, out Point point)
{
if (x and y are inside bounds)
{
point = new Point(x, y);
return true;
}
point = default(Point);
return false;
}
//...
}
And the code adding points to the list should act based upon creation success.
Fun fact: if you are using C# 7 the code could look a lot cleaner:
public static (bool Succesful, Point NewPoint) TryCreatePoint(int x, int y, Bounds bounds)
{
if (x and y are inside bounds)
return (true, new Point(x, y));
return (false, default(Point));
}
I can think of three options:
Have the constructor throw an exception that you catch. This is not really great if you are expecting a lot of failures.
Have an IsValid property on the struct that you can use to filter it out once created.
Have the thing loading the data take responsibility for validating the data as well. This would be my preferred option. You say "it does not feel right because caller would have to handle logic that should reside in Point" but I would argue that the responsibility for checking that loaded data is correct is with the thing loading the data, not the data type. You could also have it throw an ArgumentOutOfRangeException in the constructor if the inputs are not valid now that you are no longer expecting anything invalid to be passed as a belt and bracers approach to things.
What you want to do is simply not posible, an instance of a class is either fully created or not at all. If the constructor has been called the only way to not instantiate an instance is by throwing an exception.
So you have these two opportunities to do this:
Extract a method Validate that returns a bool and can be called from the caller of your class.
public struct Point
{
public int X, Y { get; }
public Point(int x, int y)
{
}
}
public bool Validate() { return -1000 <= X && X <= 1000 && -1000 <= Y and Y <= 1000; }
Of course you could do the same using a property.
Throw an exception in the constructor
public Point(int x, int y)
{
if(x > 1000) throw new ArgumentException("Value must be smaller 1000");
// ...
}
However the best solution IMHO is to validate the input before you even think about creating a point, that is check the arguments passed to the constructor beforehand:
if(...)
p = new Point(x, y);
else
...
To be honest, Point shouldn't check boundaries, so the caller should do that. A point is valid in the range that their X and Y can operate (int.MinValue and int.MaxValue). So a -1000000,2000000 is a valid point. The problem is that this point isn't valid for YOUR application, so YOUR application (the caller), the one who is using point, should have that logic, not inside the point constructor.
Structs in C# are funny so I'll add another "funny" way to check:
struct Point
{
int _x;
public int X
{
get { return _x; }
set { _x = value; ForceValidate(); }
} // simple getter & setter for X
int _y;
public int Y
{
get { return _y; }
set { _y = value; ForceValidate(); }
} // simple getter & setter for Y
void ForceValidate()
{
const MAX = 1000;
const MIN = -1000;
if(this.X >= MIN && this.X <= MAX && this.Y >= MIN && this.Y <= MAX)
{
return;
}
this = default(Point); // Yes you can reasign "this" in structs using C#
}
}
I can't seem to figure our what the issue is here. pph and with both equal to different values in the different overloads. I'm not sure what I'm doing wrong. I don't see how the values are the same.
public class Pay
{
public double ComputePay(double h,double pph,double with)
{
double net = 0;
try
{
double gross = h * pph;
net = gross - with;
}
catch (FormatException)
{
Console.WriteLine("Hour's cannot be less than zero");
}
return net;
}
public double ComputePay(double h, double pph, double with = 0.15)
{
double net = 0;
try
{
double gross = h * pph;
net = gross - with;
}
catch (FormatException)
{
Console.WriteLine("Hour's cannot be less than zero");
}
return net;
}
public double ComputePay(double h, double pph = 5.85, double with = 0.15)
{
double net = 0;
try
{
double gross = h * pph;
net = gross - with;
}
catch (FormatException)
{
Console.WriteLine("Hour's cannot be less than zero");
}
return net;
}
}
I'm not sure what I'm doing wrong.
You've got three methods which both have three double parameters:
public double ComputePay(double h,double pph,double with)
public double ComputePay(double h, double pph, double with = 0.15)
public double ComputePay(double h, double pph = 5.85, double with = 0.15)
The fact that some of the parameters in some of the method declarations are optional is irrelevant to overloading here - you simply can't specify three methods like that. Which method would you expect to be called if the caller specifies three arguments?
Why do you want three methods anyway, given that they all do the same thing? Just get rid of the first two.
You cannot have two or more methods with the same signature. This means that they cannot have the same name and parameter-types. This has nothing to do with the value that will be passed to the method.
Correct could be:
public int Sum(int a, int b)
{
return Sum(a, b, 0);
}
public int Sum(int a, int b, int c)
{
return a + b + c;
}
Edit:
Here's an interesting MSDN-article giving guidelines about Member Overloading.
Your method signature (double, double, double) is the same. In this case, just delete the first two implementations. The last one will most likely already behave the way you want.
Your last two ComputePay (double, double, double) are the same. Having a default variable doesn't make the method different. Just use the second one and you'll be good to go.
I know that blocks can be passed to a instance method and the method can be written as follow,
-(void)Method:((void) (^)(float)f)
{
f(0.5);
}
Also, this method is also a valid expression.
-(void)Method:((void) (*)(float)f)
{
f(0.5);
}
I want to know that what can i pass to this method? And what is the usage of this?
Besides, I want to know that is there any obj-c equivalent of the following c# code? Because I am wondering that obj-c has function pointer or not.
public static float Sum(float x, float y)
{
return x+y;
}
public delegate float Operation(float x, float y);
public static Main()
{
Operation dSum = Sum;
Console.WriteLine(dSum(0.5, 1.5));
}
Your second Objective-C method takes a C function pointer whose addressed function has a float as input and returns nothing. It's the same as with the block:
typedef void (^ BlockType)(float);
- (void)blockMethod: (BlockType)block {
block(1.0);
}
[obj blockMethod:aBlock];
vs.
typedef void (* FuncType)(float);
- (void)funcMethod: (FuncType)func {
func(1.0);
}
[obj funcMethod:aFunc];
The difference being that a function cannot capture its surrounding state (and that a function is a function, and a block is a block.)
This doesn't require Objective-C; what you're trying to do can be translated pretty easily to straight C:
static float sum(float x, float y)
{
return x + y;
}
typedef float (*Operation)(float x, float y);
int main(int argc, char **argv)
{
Operation dSum = sum;
printf("%f\n", dSum(0.5, 1.5));
return 0;
}
That should all look pretty recognizable.
In C#, when defining a public method like:
public int myMethod(String someString)
{
//code
}
What does the int indicate apart from the type integer? What confuses me is that the method is using a String as arguments in this case.
It is the return type of the method. In this case a 32-bit signed integer with a range of
-2,147,483,648 .. +2,147,483,647
It corresponds to the .NET type System.Int32. int is just a handy C# alias for it.
You would return a value like this
public int Square(int i)
{
return i * i;
}
And you could call it like this
int sqr = Square(7); // Returns 49
// Or
double d = Math.Sin(Square(3));
If you do not need the return value, you can safely ignore it.
int i;
Int32.TryParse("123", out i); // We ignore the `bool` return value here.
If you have no return value you would use the keyword void in place of the type. void is not a real type.
public void PrintSquare(int i)
{
Console.WriteLine(i * i);
}
And you would call it like this
PrintSquare(7);
The method in your example accepts a string as input parameter and returns an int as result. A practical example would be a method that counts the number of vowels in a string.
public int NumberOfVowels(string s)
{
const string vowels = "aeiouAEIOU";
int n = 0;
for (int i = 0; i < s.Length; i++) {
if (vowels.Contains(s[i])) {
n++;
}
}
return n;
}
It stands for "integer", and it means the method returns an integer number of 32 bits, also known in C# as Int32.
As previously stated, it's what the method returns.
For example:
public string x()
{
return 5;
}
Would error. 5 is definitely not a string!
public int x()
{
return 5;
}
Would be correct; since 5 can be considered an int (Short for integer, which is, basically, just a number which cannot have a decimal point. There's also float, double, long and decimal, which are worth reading about)
There must be no way of it not returning, for example, if you do:
public int x()
{
if (false)
{
return 5;
}
}
It will error because if the expression is false (It is of course) it won't be returning an int, it won't return anything.
If you use the keyword void, it means it does not return anything. Ex:
public void x()
{
someFunction("xyz");
}
It's fine that it doesn't return as it's a void method.
I don't think you're new to programming judging by your reputation, but just in case, when you return something you pass it back from the method, for example:
int x;
public int seven()
{
return 7;
}
x = seven();
x will become the return value of the function seven.
Note that the 'dynamic' type works here:
public dynamic x(int x, int y)
{
if (x == y)
{
return "hello";
}
return 5
}
But if you're new to C# don't get caught up in dynamic typing just yet. :)
It is the type of the return value.
Everyone is correct here but the definition from msdn:
"Int32 is an immutable value type that represents signed integers with values that range from negative 2,147,483,648 (which is represented by the Int32.MinValue constant) through positive 2,147,483,647 (which is represented by the Int32.MaxValue constant. The .NET Framework also includes an unsigned 32-bit integer value type, UInt32, which represents values that range from 0 to 4,294,967,295."
Found here on MSDN: Int32 Structure
I suggest you read the documentation found in the link above. It is extremely useful.