I want to change CultureInfo of double or the string.
For example I get double value from the code in format like 3015.0
I don't know in what unit is this but I need value in the meters and these are not in the meters because I am on the altitude of cca.100m
I have tried: double.Parse(test, new System.Globalization.CultureInfo("hr-HR"));
and double.Parse(test, new System.Globalization.CultureInfo());
but nothing is a right format what I need.
Any idea what I can do? This is windows form C# application if this is important. Framework 4.0
EDIT:
As you can see on this LINK I had a similar problem before and it was solved with culture info. Problem is that on picture 1 are the values that I get and on the picture 2 are the real values that I need to get ( when I say real I mean in the right format) I think that problem is in the culture somewhere as on my previously question I had problem with decimal values).
This is not related to Culture info.
Looks like you are getting a measurement in feet while you are expecting it to be in meters. In fact, 100 meters = 328.08399 feet and your measurements might be in 10 feets i.e 3015.0 = 301.5 feet (some GPS receivers do not support floats or doubles and therefore return only integers multiplied by 10 to have one decimal accuracy)
If you are using a cheap GPS receiver than this is expected as the accuracy is not that great (this would explain why you are getting 3015.0 instead of 3280)
I hope this helps.
Your problem has nothing to do with CultureInfo but with unit conversion. Probably you will have to do a unit convertion. Are you sure that the number is not 301.5? This would probably mean that the altitue is given in feet.
double altitudeMeters = 0.3048 * altitudeFeet;
The setting of the current culture will not convert units for you. It only affects the formatting of numbers (for example, some cultures use a comma instead of a period for the decimal point). You'll have to do the units conversion yourself.
double.Parse will simply convert the string into a number. It doesn't do unit conversions. The different culture information is for when there is a decimal comma (e.g. French) etc.
You will have to build some logic into your application to convert the number from what looks like feet to meters. If you can be sure that the data is always going to be in the "wrong" format then a simple feet to meters (1 foot = 0.3048 meters) conversion will work. Given that this is a GPS device you might be able to assume this.
If the numbers can be in any format then you will need to analyse the number and if it's outside the sensible range convert it. However, this will fail if someone enters "100". Is this metres or feet?
To ensure you get the right units you will either have to have the user select the units on a separate control or include the units in the input string. If you do the latter then you'll need to get into parsing the string to see if it contains a units string, stripping it off, parsing the number and the string and then doing the conversion.
Altitude comes from $GPGGA string which indicates the units being used. What does the $GPGGA string look like?
see http://aprs.gids.nl/nmea/#gga
if you look at the raw data in the string you will know if you are collecting the right numbers and their units
Alex
Related
Is there any possibility to force a parameter tpye to accept only a given format and not only in runtime?
What I mean, for instance I have a method:
public void AcceptTest(double version)
{
}
This method will accept 1.0 but 1.00, 1.0067 and so on.
How can I solve to accept only x.y and nothing else but without check it from code by String.Format or something else.
So I don't even give the possibility to write an unacceptable format in the code editor also.
Thank you!
Your goal is not quite clear, and depending on it any number of answer are possible. Including several that read "you are on a poor track" and "that is impossible".
You can not with Double. Double is defined as a number with a high possibility for decimal places. Every number from it's range is viable, both at compile and runtime.
You could round it automatically, wich might be considered poor behavior.
You could check if the "input" is the same as the "input rounded to the 1st decimal digit" (to see if the other party did the rounding for your).
Note that float imprecision will still result in ending up with wierd decimal places. This is a inherent part of floating point numbers:
https://www.youtube.com/watch?v=PZRI1IfStY0
Some implementations of decimal allow you to specify how many digits after comma to allow. But the .NET one is not among them. At least it avoids the decimal imprecision by lowering the value range.
You could just store as (unsigned) integer. Setting the comma during output would become a display side thing. Maybe make your own structure for this so you can provide your own ToString().
Hop that helps, but calrification would be nessesary. In particular your goal and intention. or the specific problem that makes such a limitation nessesary.
I hope I have researched this enough that my premise is not totally off base. If so, then the mathematicians out there can set me straight.
My premise is that a Double value such as 12.5 should be rounded to 5 significant figures (NOT decimal places) as 12.500. Instead, using the following C# code, I get 12.5:
Double d = 12.5;
Console.WriteLine(d.ToString("G5"));
I came across this post from 2007 which seems to echo my problem. In fact, I am using those example numbers just to keep things consistent.
My goal here is to better understand the following:
Is my understanding of sig figs mathematically correct? I.e., is my expectation reasonable, or is the output "12.5" somehow correct?
Is this really a (very long-lived) bug in the framework? If so, can/will it be fixed?
Assuming it is a bug, what might I do about it now? Write a hack to determine how many
sig figs you actually got back and then pad it? Roll my own code to
do what the "G" format string was supposed to do? I have come across examples of this on SO already, so perhaps that is evidence that a clean option does not exist.
Additionally, I do realize that the storage issues with Double might negatively impact the rounding aspect of this problem, but for now, I am only concerned with the issue of more sig figs than original digits.
EDIT: I have tested this up to framework 4.5.
See this link on G-Format Specifier. It clearly states:
The result contains a decimal point if required, and trailing zeros after the decimal point are omitted.
A Double value is rounded to 15 significant figures, not five.
Reference: The General ("G") format specifier
Rounding a number to any number of significant figures doesn't mean that the formatted string has to contain that number of digits. If the value is rounded to 12.5000000000000 then it will be formatted into "12.5" because that is the most compact way to represent the value.
Why can't c# do any exact operations.
Math.Pow(Math.Sqrt(2.0),2) == 2.0000000000000004
I know how doubles work, I know where the rounding error is from, I know that it's almost the correct value, and I know that you can't store infinite numbers in a finite double. But why isn't there a way that c# can calculate it exactly, while my calculator can do it.
Edit
It's not about my calculator, I was just giving an example:
http://www.wolframalpha.com/input/?i=Sqrt%282.000000000000000000000000000000000000000000000000000000000000000000000000000000001%29%5E2
Cheers
Chances are your calculator can't do it exactly - but it's probably storing more information than it's displaying, so the error after squaring ends up outside the bounds of what's displayed. Either that, or its errors happen to cancel out in this case - but that's not the same as getting it exactly right in a deliberate way.
Another option is that the calculator is remembering the operations that resulted in the previous results, and applying algebra to cancel out the operations... that seems pretty unlikely though. .NET certainly won't try to do that - it will calculate the intermediate value (the root of two) and then square it.
If you think you can do any better, I suggest you try writing out the square root of two to (say) 50 decimal places, and then square it exactly. See whether you come out with exactly 2...
Your calculator is not calculating it exactly, it just that the rounding error is so small that it's not displayed.
I believe most calculators use binary-coded decimals, which is the equivalent of C#'s decimal type (and thus is entirely accurate). That is, each byte contains two digits of the number and maths is done via logarithms.
What makes you think your calculator can do it? It's almost certainly displaying less digits than it calculates with and you'd get the 'correct' result if you printed out your 2.0000000000000004 with only five fractional digits (for example).
I think you'll probably find that it can't. When I do the square root of 2 and then multiply that by itself, I get 1.999999998.
The square root of 2 is one of those annoying irrational numbers like PI and therefore can't be represented with normal IEEE754 doubles or even decimal types. To represent it exactly, you need a system capable of symbolic math where the value is stored as "the square root of two" so that subsequent calculations can deliver correct results.
The way calculators round up numbers vary from model to model. My TI Voyage 200 does algebra to simplify equations (among other things) but most calculators will display only a portion of the real value calculated, after applying a round function on the result. For example, you may find the square root of 2 and the calculator would store (let's say) 54 decimals, but will only display 12 rounded decimals. Thus when doing a square root of 2, then do a power of that result by 2 would return the same value since the result is rounded. In any case, unless the calculator can keep an infinite number of decimals, you'll always have a best approximate result from complexe operations.
By the way, try to represent 10.0 in binary and you'll realize that you can't represent it evenly and you'll end up with (something like) 10.00000000000..01
Your calculator has methods which recognize and manipulate irrational input values.
For example: 2^(1/2) is likely not evaluated to a number in the calculator if you do not explicitly tell it to do so (as in the ti89/92).
Additionally, the calculator has logic it can use to manipulate them such as x^(1/2) * y^(1/2) = (x*y)^1/2 where it can then wash, rinse, repeat the method for working with irrational values.
If you were to give c# some method to do this, I suppose it could as well. After all, algebraic solvers such as mathematica are not magical.
It has been mentioned before, but I think what you are looking for is a computer algebra system. Examples of these are Maxima and Mathematica, and they are designed solely to provide exact values to mathematical calculations, something not covered by the CPU.
The mathematical routines in languages like C# are designed for numerical calculations: it is expected that if you are doing calculations as a program you will have simplified it already, or you will only need a numerical result.
2.0000000000000004 and 2. are both represented as 10. in single precision. In your case, using single precision for C# should give the exact answer
For your other example, Wolfram Alpha may use higher precision than machine precision for calculation. This adds a big performance penalty. For instance, in Mathematica, going to higher precision makes calculations about 300 times slower
k = 1000000;
vec1 = RandomReal[1, k];
vec2 = SetPrecision[vec1, 20];
AbsoluteTiming[vec1^2;]
AbsoluteTiming[vec2^2;]
It's 0.01 second vs 3 seconds on my machine
You can see the difference in results using single precision and double precision introduced by doing something like the following in Java
public class Bits {
public static void main(String[] args) {
double a1=2.0;
float a2=(float)2.0;
double b1=Math.pow(Math.sqrt(a1),2);
float b2=(float)Math.pow(Math.sqrt(a2),2);
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(a1)));
System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(a2)));
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(b1)));
System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(b2)));
}
}
You can see that single precision result is exact, whereas double precision is off by one bit
Does anyone know of an elegant way to get the decimal part of a number only? In particular I am looking to get the exact number of places after the decimal point so that the number can be formatted appropriately. I was wondering if there is away to do this without any kind of string extraction using the culture specific decimal separator....
For example
98.0 would be formatted as 98
98.20 would be formatted as 98.2
98.2765 would be formatted as 98.2765 etc.
It it's only for formatting purposes, just calling ToString will do the trick, I guess?
double d = (double)5 / 4;
Console.WriteLine(d.ToString()); // prints 1.75
d = (double)7 / 2;
Console.WriteLine(d.ToString()); // prints 3.5
d = 7;
Console.WriteLine(d.ToString()); // prints 7
That will, of course, format the number according to the current culture (meaning that the decimal sign, thousand separators and such will vary).
Update
As Clement H points out in the comments; if we are dealing with great numbers, at some point d.ToString() will return a string with scientific formatting instead (such as "1E+16" instead of "10000000000000000"). One way to overcome this probem, and force the full number to be printed, is to use d.ToString("0.#"), which will also result in the same output for lower numbers as the code sample above produces.
You can get all of the relevant information from the Decimal.GetBits method assuming you really mean System.Decimal. (If you're talking about decimal formatting of a float/double, please clarify the question.)
Basically GetBits will return you 4 integers in an array.
You can use the scaling factor (the fourth integer, after masking out the sign) to indicate the number of decimal places, but you should be aware that it's not necessarily the number of significant decimal places. In particular, the decimal representations of 1 and 1.0 are different (the former is 1/1, the latter is 10/10).
Unfortunately, manipulating the 96 bit integer is going to require some fiddly arithmetic unless you can use .NET 4.0 and BigInteger.
To be honest, you'll get a simpler solution by using the built in formatting with CultureInfo.InvariantCulture and then finding everything to the right of "."
Just to expand on the point about getbits, this expression gets the scaling factor from a decimal called foo:
(decimal.GetBits(foo)[3] & 16711680)>>16
You could use the Int() function to get the whole number component, then subtract from the original.
One of the fun parts of multi-cultural programming is number formats.
Americans use 10,000.50
Germans use 10.000,50
French use 10 000,50
My first approach would be to take the string, parse it backwards until I encounter a separator and use this as my decimal separator. There is an obvious flaw with that: 10.000 would be interpreted as 10.
Another approach: if the string contains 2 different non-numeric characters, use the last one as the decimal separator and discard the others. If I only have one, check if it occurs more than once and discards it if it does. If it only appears once, check if it has 3 digits after it. If yes, discard it, otherwise, use it as decimal separator.
The obvious "best solution" would be to detect the User's culture or Browser, but that does not work if you have a Frenchman using an en-US Windows/Browser.
Does the .net Framework contain some mythical black magic floating point parser that is better than Double.(Try)Parse() in trying to auto-detect the number format?
I think the best you can do in this case is to take their input and then show them what you think they meant. If they disagree, show them the format you're expecting and get them to enter it again.
I don't know the ASP.NET side of the problem but .NET has a pretty powerful class: System.Globalization.CultureInfo. You can use the following code to parse a string containing a double value:
double d = double.Parse("100.20", CultureInfo.CurrentCulture);
// -- OR --
double d = double.Parse("100.20", CultureInfo.CurrentUICulture);
If ASP.NET somehow (i.e. using HTTP Request headers) passes current user's CultureInfo to either CultureInfo.CurrentCulture or CultureInfo.CurrentUICulture, these will work fine.
You can't please everyone. If I enter ten as 10.000, and someone enters ten thousand as 10.000, you cannot handle that without some knowledge of the culture of the input. Detect the culture somehow (browser, system setting - what is the use case? ASP? Internal app, or open to the world?), or provide an example of the expected formatting, and use the most lenient parser you can. Probably something like:
double d = Double.Parse("5,000.00", NumberStyles.Any, CultureInfo.InvariantCulture);
The difference between 12.345 in French and English is a factor of 1000. If you supply an expected range where max < 1000*min, you can easily guess.
Take for example the height of a person (including babies and children) in mm.
By using a range of 200-3000, an input of 1.800 or 1,800 can unambiguously be interpreted as 1 meter and 80 centimeters, whereas an input of 912.300 or 912,300 can unambiguously be interpreted as 91 centimeters and 2.3 millimeters.