What is the best way to recognize and convert these "minimum" double values ​​to C # Double.MinValue?

I have a database table that needs to be converted to the current form. This table has three columns of type Double (it Pervasive.SQL , if anyone is interested).

My problem is that this table has been around for a long time, and it has been affected by code returning about 15 years or better.

Historically, we always used Double.MinValue (or any other language equivalent at the time) to represent the "blank" values ​​provided by the user. The absence of meaning, in other words, is actually preserved as a value that we can recognize later and respond reasonably.

So, today my problem is that I need to iterate over these records and insert them into the newly created table (this is the "conversion" that I talked about). However, I do not see the consistent values ​​in the tables that I convert. Here are the ones that I know for sure:

 2.2250738585072014E-308 3.99285938963E-313 3.99099435427E-313 1.1125369292536007E-308 -5.389000690742776E279 2.104687961E-314 

Now I understand that there are other ways that Double.MinValue can exist, or at least be represented. After doing some Google searches, I found that the former is a different Double.MinValue (actually DBL_MIN , which is referenced here: http://msdn.microsoft.com/en-us/library/6bs3y5ya(v=vs.100 ) .aspx ).

I do not want to be too long, so I will ask questions if this is not enough to help me. Suffice it to say, I need a reliable way to determine all the previous “minimum” values ​​and replace them with the C # Double.MinValue constant when I Double.MinValue over these data rows.

If this turns out to be dataRow["Value"] < someConstant , then so be it. But I will allow mathematical theorists to help me in this decision.

Thanks for this time.

EDIT:

This is what I do with these values ​​when I find them. This is part of a general method that collects the values ​​that should be written to the database:

 else if (c.DataType == typeof(System.Double)) { if (inRow[c] == DBNull.Value) retString += @"NULL"; else { Double d; if (Double.TryParse(inRow[c].ToString(), out d)) retString += d.ToStringFull(); } } 

Until now, he just accepted them. And this is bad, because when the application finds them, they look like acceptable data, and not like Double.MinValue. Therefore, they are not considered spaces. But that is what they are.

+4
source share
2 answers

This is absolute madness. Let's look at some of these numbers in detail. These are all tiny numbers that are just over zero:

 2.2250738585072014E-308 

This 1/2 1022 is a normal double. This is one of two “special” numbers in your set; this is the smallest normal double that is greater than zero. The rest of the small doubles on your list are subnormal doubles.

 1.1125369292536007E-308 

This 1/2 1023 is a subnormal double. This is also a special number; this is half the smallest normal double greater than zero. (I initially said that this is the largest subnormal double, but of course this is not true, see Comments.)

 3.99285938963E-313 

This is not something special. This is a subnormal double value equal to a fractional value, where the numerator is 154145 and the denominator is a fairly large degree of two.

 3.99099435427E-313 

This is also nothing special. This time the numerator is 154073.

 2.104687961E-314 

This is also nothing special. The numerator is 2129967929, and the denominator is the even greater power of the two.

All numbers so far have been very close to zero and positive. This number is very far from zero and negative, and therefore stands out:

 -5.389000690742776E279 

But again, nothing special; it is nowhere near the negative double with the largest absolute value, which is about -1.79E308, about a billion times larger.

This is a complete mess.

My advice is to stop this madness immediately . It makes no sense to use values ​​that are incredibly close to zero to represent "empty" values; values ​​that are incredibly close to zero should be rounded to zero and not counted as spaces!

Double already has a representative for the "empty" values, namely Double.NaN - Not A Number ; it’s strange to use a valid value to represent an invalid value when a certain “invalid” value is already included in the domain. (Remember that in fact there are a large number of different NaN bit patterns, use IsNaN to determine if double NaN is.)

So my advice is:

  • Individually examine each number in the database that is subnormal or very small normal double. Some of them should probably be zero and end up as tiny values ​​due to rounding errors. Replace them with zero. Those that should be empty are replaced by a null database (best practice) or a double NaN (valid but not as good as a null database.)

  • Write a program to find every number in the database that is not possible in the absolute value, and replace it with a zero database or double NaN.

  • Update all clients so that they understand the convention that you use to represent null values.

+9
source

It seems you want to check if double really very small, positive or really big, finite and negative. (Others have detailed some of the problems with your approach in the comments, I will not go into this here.) A test like this:

 if (d == d && (d > 0 && d < 1e-290 || d < -1e270 && d + d != d)) 

can do just about what you want. You may have to adjust the numbers above. The test d == d checks the value of NaN , and the test d + d != d checks the infinity.

0
source

Source: https://habr.com/ru/post/1484228/


All Articles