How to transform a different notation floating point number to double? - c#

I'm currently trying to convert a few numbers from a DB2 Server into double values in C#.
The getting of the data from the DB2 Server is not a Problem, and I get the data into a DataTable quite easily. The Problem then Comes when I try to convert the objects into double values, as the Notation is different (, instead of . as example).
Thus the code:
foreach (DataRow row in DataTable myResultTable)
{
double myValue = String.IsNullOrEmpty(row["myValue"].ToString())? 0 : (double)row["myValue"]; // myValue has 1234,56 as Content.
}
Fails with an exception that the value can't be converted.
The datatype of the field myValue in the db2 is Decimal with a length of 16.
As I didn't find anything, I thought about converting it to string, formating it there and then transform that into a double but that seems quite....complicated to me for something that should be easy (and complicated always means prone to Errors because of something unexpected).
So my question is: Is there any easy way to do this Transformation?
Edit:
As it was asked a GetType on row["myValue"] results in: {Name = "Decimal" FullName = "System.Decimal"}.

The real solution is to cast to decimal not to double:
var value = row["myValue"] is DBNull ? 0m : (decimal)row["myValue"];

Related

How to get double value with SqlDataReader

I'm trying read data from sql database. When I run the code, it gives an error when it comes to where it should read data.
"System.InvalidCastException: Specified cast is not valid."
I get an error. I researched my mistake but couldn't find the solution that works for me. While the query text I wrote works in ssms, it does not work in code.
private void pbx_frame_MouseUp(object sender, MouseEventArgs e) //
{
//take cropped image to picture box of crooped images
try
{
string[] resim = lbx_raw_image.SelectedItem.ToString().Replace(':','.').Split('.');
string sorgu_sql = "Data Source=DESKTOP-OON7EET\\SQLEXPRESS;Initial Catalog=Target;Integrated Security=True;"; //sql bağlantısı kuruldu
//string query = "SELECT * FROM MP_Data$ WHERE time= '19.53.06'"; //'" + lbx_raw_image.SelectedItem.ToString() + "'"; //time=19.53.06 tek bir veriyi çağrır. muhtemelen yorum haline getirilen kısım olacaktı.
string query = "SELECT * FROM MP_DATA_15_mayıs_2019$ WHERE time='" + lbx_raw_image.SelectedItem.ToString() + "'"; //12.50.23
DB_islem db = new DB_islem(sorgu_sql, query); //
pic_info_from_MP = db.Raw_Image(pic_info_from_MP);
public Target Raw_Image(Target pic_info)
{
sql.Open();
sql_read = sql_command.ExecuteReader();
//while (sql_read.Read())
if (sql_read.Read())
{
pic_info.lat = sql_read.GetDouble(0);
pic_info.lon = sql_read.GetDouble(1);
pic_info.alt = sql_read.GetDouble(2);
pic_info.yaw = sql_read.GetDouble(3);
}
sql.Close();
return pic_info;
}
SOLUTİON:
ALTER TABLE table1(name of table) ALTER COLUMN clmn1(name of column) float(datatype);
I determined datatype for each column using the above query. helped me to call the required data.
The reason I asked for the table definition is because there are particular column types on the DB side that map to particular data types on the C# side. The screenshot posted is not enough to realistically determine the column types. The lat and long aren't real, otherwise they'd be truncated but other than that we can't really say
Broadly speaking:
If you've used real column type, call GetFloat(..)
If you've used float column type, call GetDouble(..)
If you've used decimal(or numeric) column type, call GetDecimal(..)
GetXxx will not convert for you because it does an unboxing cast. If your reader has a decimal in column 0 you can only call GetDecimal on it. You cannot call GetDouble and expect you really-a-decimal to be converted to a double, for the same reason as this doesn't work:
object o = 0.1m; //decimal boxed inside object
double d = (double)o;
Unboxing casts and converting casts are different things. If you want your decimal-in-an-object as a double you have to cast twice, once to unbox and once to convert:
object o = 0.1m; //decimalboxed inside object
double d = (double)(decimal)o;
Similarly if your thing inside reader column 0 is a decimal and you want a double you must get it as a decimal, because that's what it really is, and then convert it:
var dbl = (double)reader.GetDecimal(0);
Simple rule:
Pull it out according to what it really is, then convert it
As to what you have, we don't know; your yaw could be a real and cannot be GetDouble'd (has to be GetFloat'd). Your alt is probably a decimal (do you really need altitude to the tenth of a picometer/pico-ft?) and cannot be GetDouble'd (has to be GetDecimal'd) .. but you have all the necessary info to solve this one yourself.
If all else fails and the above just went completely over your head "try changing GetDouble to GetDecimal for the line that doesn't work. And if that doesn't work, try changing it to GetFloat. And if that doesn't work, supply the table definition and we'll tell you what it should be"
Update: youve indicated they're all varchar. Personally I would convert them to float or real - open SSMS, Design the table, change the column type to eg float and save the table. Then they can be GetDouble'd
First of all you should execute your queries ONLY with parameters.
Secondly, we don't know your table schema - please show it.
But most probably there is problem in how you store this value. GetDouble doesn't do any conversions, so your data should already be saved as double.
What's more, there can be problem with globalization. What you should do is:
using System.Globalization;
//...
double result = double.NaN;
if(!sql_read.IsDbNull(0))
{
string s = sql_read.GetString(0);
result = Convert.ToDouble(s, CultureInfo.InvariantCulture);
}

How to cast/convert values from JSON?

My background is all in dynamic languages for many years, so reasoning about how static typed languages get data from JSON where the key/values can be different types is becoming an issue that really has me stuck. Here's an example of the data I have:
{
"par": 4,
"level": [0,1,0,1,1, 0,1,0,1,1, 0,1,0,1,1, 0,1,0,1,1, 0,1,0,1,1]
}
And I want to get this into some local variables like these
int par;
List<bool> levelData;
I'm using MiniJSON.cs to do the parsing, and it gives me back Dictionary<string, object> but I can't figure out how to get the par and level values from that and convert them to the different types they actually represent.
The problem with trying to convert to List<int> was that MiniJSON parses integers into Int64 and int is 32-bit, so the conversion won't be allowed implicitly because of data loss. Converting to a list of Int64 worked!
List<Int64> cells = (List<Int64>)data["level"];
You have to provide a "decoder" that transforms the dictionary into a typed data structure. This is especially obvious since you are using 0 and 1 to represent boolean values.
Suppose the class SomeClass holds your typed data. The decoder would have to do something like this:
SomeClass decode(Dictionary<string,object> d) {
var m = new SomeClass();
m.par = (int)d["par"];
m.levelData = ((List)d["level"]).Select(x => (int)x == 0 ? false : true).ToList();
return m;
}
So, basically you must turn the (untyped) objects into typed values, and you have to do that explicitly. Note that here it is assumed that your list of zeroes and ones is homogeneous (i.e. does not contain "strange" values like strings, which would be perfectly legal in a dynamically typed language).

Check to see if JavaScript value is a Decimal

I'm working on an app. I'm using JavaScript to save values to a database. My database table has a column that holds a Decimal value. It works fine with some old C# code. In fact, in C#, I'd do this:
decimal? myValue = null;
decimal temp = 0;
if (Decimal.TryParse(myString, out temp)) {
myValue = temp;
}
I understand that JavaScript only has a single Number type. However, because I'm saving my value to the database, how do I ensure that its a decimal? In C#, I know that a Float is basically a 32-bit value, a Double is basically a 64-bit value, and a Deciml is basically a 128-bit value. However, I'm not sure how to translate this to JavaScript.
Can anyone provide some insights?
Thanks!
You would check for decimals in javascript like this:
var dec = 3.14;
if(typeof dec == "number" && (dec+'').indexOf('.')!=-1){
var myvalue = dec;
}
Note that the above will fail on numbers such as 5.00 as noted by FelixKling as the decimals are lost when it is converted to String.

Error Converting data type 'Numeric' to Decimal (help!)

Good Day Everyone,
As of now im stuck with this error
Error Converting data type 'Numeric' to Decimal
this is my code
AddManualItems AddReconItem = new AddManualItems();
UserAccess user = new UserAccess();
AddReconItem.BranchCode = BranchCodeTextBox.Text;
AddReconItem.ForLoanMonth = YearDropDownList.SelectedValue + "/" + MonthDropDownList.SelectedValue;
AddReconItem.ItemWeight = Convert.ToDecimal(WeightTextBox.Text);
AddReconItem.PrincipalAmount = Convert.ToDecimal(PrincipalTexAmTextBox.Text);
AddReconItem.PawnTicket = PwnTicketTextBox.Text;
AddReconItem.ItemStorageGroup = Convert.ToInt16(StorageNameDropDownList.SelectedValue);
AddReconItem.ReconID = Convert.ToInt16(ReconTypeDropDownList.SelectedValue);
user.UserID = Session["UserID"].ToString();
string a = servs.AddItemRecon(user, AddReconItem); // this is where the error appears in debug mode
the code inside of the ADDitemRecon(User,AddReconItem) is this
using (SqlConnection reportsConn = new SqlConnection(sqlConnWriter))
{
reportsConn.Open();
SqlCommand AddReconItem = new SqlCommand();
AddReconItem.Connection = reportsConn;
AddReconItem.CommandType = CommandType.StoredProcedure;
AddReconItem.CommandText = "Updater.usp_AddReconcileItems";
AddReconItem.Parameters.AddWithValue("#ITEMWEIGHT", Convert.ToDecimal( items.ItemWeight));
AddReconItem.Parameters.AddWithValue("#ITEMPRINCIPALAMT", Convert.ToDecimal(items.PrincipalAmount));
AddReconItem.Parameters.AddWithValue("#FORLOANMONTH", Convert.ToDateTime(items.ForLoanMonth));
AddReconItem.Parameters.AddWithValue("#STORAGEGROUPID", items.ItemStorageGroup);
AddReconItem.Parameters.AddWithValue("#BRANCHCODE", items.BranchCode);
AddReconItem.Parameters.AddWithValue("RECONID", items.ReconID);
AddReconItem.Parameters.AddWithValue("#PAWNTIX",items.PawnTicket);
AddReconItem.Parameters.AddWithValue("#CREATEDBY", user.UserID.ToString());
AddReconItem.ExecuteNonQuery();
}
my property for ItemWeight is
private decimal itemWeight;
public decimal ItemWeight
{
get { return itemWeight; }
set { itemWeight = value; }
}
i bet the error is in the item weight because when i input in the item weight
12345.12 it works fine, but when i input 1234 instead of treating it as 1234.00 it treats it as 1234 only making it numeric..
any help? i do not know if my conversions are wrong
By the way my field in database is
fld_ItemWeight (decimal (38,6), not null
EDIT**
Is there any bugs known in Decimal?? im using VS 2005 as of now.
Found The answer! my stored Procedure is wrong i have decimal(9,6) in my stored procedured making it accept 3 digits or less !changed it to (18,2)\
Although the original poster has found his solution, for the benefit of other people, I thought I would post what caused it for me.
System.Data.SqlClient.SqlException : Error converting data type numeric to decimal.
Sadly the message doesn't say which parameter it is having the problem with. So I changed all of the parameters that I was passing through to have a value of 0 (which is a suitable value for most SQL types, you may need to use other values), this made the error go away. I could then put them back to normal, one by one, and each time, I re-tested. That's how I worked out which parameter had the problem.
It turned out that for one of the parameters the value that I had in my code (a C# decimal) was too large to go in the decimal(7,2) stored procedure parameter.
I don't know what the proper solution for this issue , But i have one idea. Like
Change your ItemWeight property DataType decimal to string
decimal xxxyyy = Convert.ToDecimal(WeightTextBox.Text);
if(!xxxyyy .ToString().Contains(".00))
{
AddReconItem.ItemWeight=xxxyyy.ToString() +".00";
}
else
{
AddReconItem.ItemWeight=xxxyyy.ToString() ;
}
Edit :
Try this another way for use math.Round()
AddReconItem.ItemWeight = Convert.ToDecimal(WeightTextBox.Text);
AddReconItem.ItemWeight=Math.Round(AddReconItem.ItemWeight,2);
Try to round your value in set.
private decimal itemWeight;
public decimal ItemWeight
{
get { return itemWeight; }
set { itemWeight = Math.Round(value,yourPrecisionHere); }
}
Change Sql column to Decimal(18,2), Same in store procedure and take SqlDbType.Decimal at ado.net end
My problem was that the column had the right precision and scale(16,2) but the variable I was using as a parameter in the procedure hadn't(14,2).
So, when trying to insert something like 99999999999999 using the procedure, I was getting the error Error converting data type numeric to numeric.
when you are calling a procedure and it has a parameter with a decimal datatype then you can pass only in fractions. For more details please refer Error converting data type numeric to decimal

C# object and string conversion

I have following section of code in my program:
object val;
val = arr[1].Trim(); // in my case i am getting value here is 1.00
now when I am assigning value to a datarow I am getting error
Expected int64 value.
datarow[Convert.ToString(drow["col"]).Trim().ToUpper()] = val;
I am not facing any issue when getting value other that 1.00.
What could be the exact problem? How can I solve it?
Suggestions and solutions are welcome
If that column in your datatable is expecting an Int64 you need to convert val (which is a string) to an Int64:
var val = arr[1].Trim(); // String at this point
long longVal = 0;
if(!long.TryParse(val,out longVal){
throw new InvalidOperationException("value wasnt an Int64!");
}
datarow[Convert.ToString(drow["col"]).Trim().ToUpper()] = longVal
arr[1] seems to be string, and applying .Trim() keeps it as a string, even if it's "1.00". If you need an integer, you need to parse it. However, it can't be parsed to an intteger, because it's actually a double.
As a proof of whether I'm right or not, you can try (Int64)double.Parse(val) and that should work. However, it's up to you to decide whether that's not an issue for your program. There's two possible issues:
val might not be parse-able to double, in which case you will get an exception
val might be a double, but not one that can be represented as an int (too large, or lose precision ex. "1.8" would become 1)
Hope this helps

Categories