Asp.net C# math problem - c#

I'm trying to build a "simple" web app that calculates either a male or females body fat % based on the U.S. Navy's circumference formula. I have the majority of the app completed at this point. However, I cannot figure out why the way I've setup the formula below won't work. Two of the values are underlined in red in my .cs file.
My Formula:
TBBodyFat.Text = Convert.ToString(495 / (1.0324-.19077(Math.Log(Convert.ToDouble(TBWaist.Text)-Convert.ToDouble(TBNeck.Text)))+.15456(Math.Log(Convert.ToDouble(TBHeight.Text)))));
Original Example:
%Fat=495/(1.0324-.19077(log(abdomen-neck))+.15456(log(height)))-450
Pop-Up for the two underlined values (.19077 and .15456):
struct System.Double
Represents a double-precision floating-point number.
Error:
Method name expected

TBBodyFat.Text = Convert.ToString(495 / (1.0324-.19077*
(Math.Log(Convert.ToDouble(TBWaist.Text)-Convert.ToDouble(TBNeck.Text)))+.15456*
(Math.Log(Convert.ToDouble(TBHeight.Text)))));
C# (not any programming language I've yet encountered) does not take adjacency of numbers to mean multiplication!

Well you need to use "*" for multiplication. Plus I'm not sure whether C# allows ".123" style numeric literals without leading 0.
Try:
TBBodyFat.Text =
Convert.ToString(495/
(1.0324-0.19077*(Math.Log(Convert.ToDouble(TBWaist.Text)-Convert.ToDouble(TBNeck.Text)))+0.15456*(Math.Log(Convert.ToDouble(TBHeight.Text)))));

Put * while multiplying like .8*(b-200) .If you will put directly .8(b-200) it will show error that method name expected.

Related

Getting random numbers after a simple math problem. Might be a local variable thing

I have a GUI working on the front end. But on the back end I have a little problem with my math. Code is trying to calculate how much time has gone with only starting and ending hours. (There are no info on days). So I think I found the way to calculate the hours spent on paper. But in C# I failed I think because of local variable stuff.
float start = float.Parse(textBox1.Text);
float end = float.Parse(textBox2.Text);
float hours_spent = end - start;
if (start > end) {
hours_spent = 24.00f -start + end;
}
First part is working correctly but when I give the start bigger than end, it gives me random numbers.
EDIT: When i gave 14.00 as an input and 13.00 as an output i get -76
and for input 14.00 output 12.00 i get -176 and for 18.50 to 10.25 i get -801. It is not random i can see that too my bad on choosing the words. But i dont get it what is wrong
When i gave 14.00 as an input and 13.00 as an output i get -76
You are parsing in a part of the world where . is not the decimal separator but is a common "group" separator. That is, a number like one hundred thousand plus a quarter is written 100.000,25, and not as it would be in the United States, 100,000.25. Parse assumes that the string is in the format of the current user's locale unless you tell it otherwise.
Therefore you are parsing the strings into values 1400 and 1300. Their difference is -100, which is less than 0, so you add 24 to -100 and get -76.
Same for your other case. You have 1850 and to 1025, subtract them to get -825, add 24 and you get -801.
There's nothing "random" at all here; everything is working as expected.
There is a lesson here: work backwards. You got -76. How'd that happen? You must have added 24 to something. What added to 24 gives you -76? -100. How did we get -100? And so on.
Start over. You should not be parsing floats in the first place. If this is a decimal quantity then you should be parsing a decimal, and if you know that it will always have . as the decimal separator, you should say so when you parse it. (Hint: use the version of TryParse that takes a NumberStyles and set the style correctly.)
If, on the other hand, you know that this is two integers separated by a period, then you should not be parsing it as a decimal or a float. You should be parsing an integer, then a period, then an integer.
If this is hours then a period then minutes, then again, you should not be using any of the above. Use a date and time parser to parse dates and times.
In short: use the right tool for the job you actually have to do.
Other problems with your code:
Use TryParse, not Parse, when dealing with user input. You don't know that there is a valid number in there, but Parse will crash if it gets bad input.
Your math is probably wrong. If someone puts in 100 and 200, do you really want -76 as the output?
Take a step back and ask yourself what the real business process is that you're trying to build here. Write that business process down carefully and then implement that process, not an approximation of it. Your business process probably does not say "parse a float using the rules of the current locale" but that's the code you wrote. Write code that means exactly what you intend it to mean.
UPDATE: Comments on the question indicate just how deep a hole you've gotten yourself into:
If entry time is 13.55 and exit time is 14.05 what should be the expected logical result ? It should be 10 (minutes) or 50 (numeric difference) ?
I am expecting 10 as minutes
Then absolutely you should not be parsing as float or decimal! Parsing as float or decimal is obviously completely wrong because 1.1 and 1.10 are the same value as a number, but nine minutes different if it is "hours.minutes", and you can't tell which case you are in by parsing as a number.
Again, you need to stop writing code, erase everything you've written so far, and start over. You're in a hole: stop digging deeper, fill in the hole, and get back to ground level.
You need to figure out exactly what format your strings are in, and parse exactly that format and nothing else.
So, write a specification that poses and then answers questions about what is allowed and what is not. Are negative values allowed? What if the number of minutes is more than 60? What if the minutes or hours are missing entirely? And so on.
Once you have a specification, write test cases that verify the spec. Then write an implementation, and run your tests. The code is more likely to be correct if you write the tests first.
I'm going to completely ignore providing a didactic answer in favor of trying to sidestep the problem.
Avoid writing your own parsing code. Instead, replace all your TextBoxes with DateTimePickers with Format set to Time. Then pull out the time by calling the .Value.TimeOfDay property. TimeOfDay is a TimeSpan, so it supports simple arithmetic.
Warning: Watch out when pulling these results using the provided properties. For example, 150 minutes can be translated as either 2 .Hours and 30 .Minutes or to 150 .TotalMinutes .

ColorConverter fails with parsing ScRGB

I´m trying to parse a LinearGradientBrush from Xaml strings, without any problem I use the ColorConverter.ConvertFromString for normal text or html color conversion.
Recently I came across some colors parsed from Adobe Illustrator into Expression Blend using the ScRGB formatting "sc#scA, scR, scG, scB". That seems to break the ColorConverter, as the ScA value from the Color struct seems to parse the value wrong; for example 0.2 becomes 2 and 0.5 becomes 5.
My code is fairly straightforward:
string colorStr = "sc#0.117647059, 0, 0, 0";
Color color = (Color)ColorConverter.ConvertFromString(colorStr);
Console.WriteLine(color.ScA);
Output: 1,176471E+08, Expected: 0,1176471
Is this a bug in the .NET Framework (I'm on 4)? Is there a workaround? Does anyone have a clean-fix?
You have a culture problem. Clearly you are living in a part of the world where the decimal point in a floating point value is a comma instead of a period. But your color string is formatted with a period. So when the value is converted to float, it sees the period in the string as a thousands separator, not a decimal point. And "0117647059" is indeed 1,176471e8.
You'll need to use the ColorConverter.ConvertFrom() overload, it accepts a CultureInfo reference. Pass CultureInfo.InvariantCulture. Or whack the Adobe tooling over the head somehow so it generates properly localized strings.

How to convert multiple textboxes to one value

In my WPF application the user is inputting a GPS coordinates in the format of Degrees : Minutes : Seconds as decimal fraction of minutes.
So 60° 30' 45" would be entered as 60° 30.750' .
I then store it as a pure decimal number so the above example would be stored as 60.5125.
The idea was that so the users wouldn't mess up the input it would be set in 3 different textboxes. One for Degrees, other for Minutes and one for the fractionalSeconds. It's somewhat bad that one of the numbers is seperated into two textboxes but if they have to type the whole number in the are afraid of all the point or comma confusion and that they could mess up.
So one thing I thought might work was a IMultiValueConverter but it seems to only work with MultiBindings which is something I'm not doing here.
Currently my solution is to bind to different properties and do all the calculations in code behind but I'm not really happy about the fractional bit. I assume 3 fractional letters but if they enter only 7 and assume 0.700 but get 0.007 so I thought I would have to do a string format bit.
Is there a better solution out there. Can I use MultiValueConverter for something like this?
You could try using a MaskedTextBox, such as the one from the Extended WPF Toolkit.
You could use a Masked TextBox. This implementation uses MaskedTextProvider which is a .net class.

string(";P") is bigger or string("-_-") is bigger?

I found very confusing when sorting a text file. Different algorithm/application produces different result, for example, on comparing two string str1=";P" and str2="-_-"
Just for your reference here gave the ASCII for each char in those string:
char(';') = 59; char('P') = 80;
char('-') = 45; char('_') = 95;
So I've tried different methods to determine which string is bigger, here is my result:
In Microsoft Office Excel Sorting command:
";P" < "-_-"
C++ std::string::compare(string &str2), i.e. str1.compare(str2)
";P" > "-_-"
C# string.CompareTo(), i.e. str1.CompareTo(str2)
";P" < "-_-"
C# string.CompareOrdinal(), i.e. CompareOrdinal(w1, w2)
";P" > "-_-"
As shown, the result varied! Actually my intuitive result should equal to Method 2 and 4, since the ASCII(';') = 59 which is larger than ASCII('-') = 45 .
So I have no idea why Excel and C# string.CompareTo() gives a opposite answer. Noted that in C# the second comparison function named string.CompareOrdinal(). Does this imply that the default C# string.CompareTo() function is not "Ordinal" ?
Could anyone explain this inconsistency?
And could anyone explain in CultureInfo = {en-US}, why it tells ;P > -_- ? what's the underlying motivation or principle? And I have ever heard about different double multiplication in different cultureInfo. It's rather a cultural shock..!
?
std::string::compare: "the result of a character comparison depends only on its character code". It's simply ordinal.
String.CompareTo: "performs a word (case-sensitive and culture-sensitive) comparison using the current culture". So,this not ordinal, since typical users don't expect things to be sorted like that.
String::CompareOrdinal: Per the name, "performs a case-sensitive comparison using ordinal sort rules".
EDIT: CompareOptions has a hint: "For example, the hyphen ("-") might have a very small weight assigned to it so that "coop" and "co-op" appear next to each other in a sorted list."
Excel 2003 (and earlier) does a sort ignoring hyphens and apostrophes, so your sort really compares ; to _, which gives the result that you have. Here's a Microsoft Support link about it. Pretty sparse, but enough to get the point across.

Value in code-behind presented differently in UI

This double: 16.8999999
after theDouble = Math.Round(theDouble, 1) it shows up in the debugger as 16.9 but in the UI later on it's NOT 16.9 but 16.899999.
Why is this so?
I am developing a WP7 application and however and whenever I round a certain value, it always shows up "derounded" in the UI. I have even tried to make one last round before assigning the array to the listbox's itemssource. It's really strange and I'd appreciate any help or explanation.
I have even tried to assign a value myself just before the itemssource gets set. I assign 16.89999 and round it using the above method. In the debugger I get the expected result but then in the UI I get another result, namely, 16.899999618. Help?
Assign the value back to the variable:
mydouble = Math.Round(mydouble, 1);
Update:
Since you updated your question, you can focus on how the value is displayed instead.
Um, no: http://ideone.com/zuK9Z
I think you've made a mistake in your code. Are you doing something like this:
double theDouble = 16.8999999;
Math.Round(theDouble);
?
It should be:
double theDouble = 16.8999999;
theDouble = Math.Round(theDouble);
I have no idea but it could have something to do with how WP7 presents doubles in datacontexts. I changed the type to float and now it works perfectly. I hope someone in the same situation finds this question even though it's pretty downvoted.
Most computers use binary floating-point. Binary floating-point cannot represent 0.1 exactly (in binary, it's a recurring fraction). Thus, it also cannot represent 0.9 exactly either.
Double values are not precise by nature!
That happens because Double numbers are represented with binary digits, not decimal, so that the nearest representation of the requested number is given in the result.

Categories

Resources