var x = dr["NationalTotal"].ToString();
дает мне 333333333C# строка для преобразования с плавающей точкой недействительна?
var xxx = Convert.ToSingle(dr["NationalTotal"].ToString());
дает мне 333333344
Любые идеи, почему?
var x = dr["NationalTotal"].ToString();
дает мне 333333333C# строка для преобразования с плавающей точкой недействительна?
var xxx = Convert.ToSingle(dr["NationalTotal"].ToString());
дает мне 333333344
Любые идеи, почему?
В спецификации с плавающей точкой говорит о том, что 32-битное представление числа с плавающей точкой является
Таким образом, наибольшее целое число, которое может быть представлено без потери (целое число) точности 16777216 (0x1000000) , Простая тестовая программа, чтобы убедить вас, что это так:
#include <stdio.h>
int main(void) {
float x;
unsigned long j;
j = 0x00FFFFFC;
int i;
x = j;
for(i=0; i<10;i++) printf("%ld + %d = %f\n", j, i, x+i);
}
Выход:
16777212 + 0 = 16777212.000000
16777212 + 1 = 16777213.000000
16777212 + 2 = 16777214.000000
16777212 + 3 = 16777215.000000
16777212 + 4 = 16777216.000000
16777212 + 5 = 16777216.000000 <<< from here on, adding one more doesn't give the right answer
16777212 + 6 = 16777218.000000
16777212 + 7 = 16777220.000000
16777212 + 8 = 16777220.000000
16777212 + 9 = 16777220.000000
EDIT На основе комментариев под ним вопрос, мы медленно сходились на том, что вы были два вопроса , Не один.
Первое: «Почему это происходит?» ответил выше. Один float просто не может точно представить 333333333
, поэтому вы получите ближайшее представимое значение, которое равно 333333344
.
Второе: «Как это исправить?» первоначально ответила мне в комментариях - я повторю мой ответ здесь:
Вашего базы данных число с плавающей запятой обычно не одинарная точность - на самом деле, по умолчанию это двойная точность. Таким образом, можно решить проблему путем преобразования строки удвоить, и присваиваем его переменной двойной точности:
double xxx = Convert.ToDouble(dr["NationalTotal"]);
Я хотел бы направить вас к http://floating-point-gui.de/ - «то, что каждый программист должен знать о плавающей точкой». На самом деле существует множество путеводителей с похожими именами. Основное чтение, если вы когда-либо отклонились от использования только целых чисел (и большинство людей в какой-то момент своей карьеры программирования).
Это происходит потому, что Single
не имеет достаточной точности для хранения вашего полного номера.
Double
имеет больше точности.
+1 Вы правы. С тех пор я удалил свой ответ! – gleng
Из документов для System.Single
:
Всех чисел с плавающей точкой имеет ограниченное число значащих цифр, которое также определяет, насколько точно значение с плавающей точкой аппроксимирует реальное число. Двойное значение имеет до 7 десятичных цифр точности, хотя не более 9 цифр поддерживается внутри.
Это фактически означает, что Single
здесь, а не Double
, но дело в том, что вы пытаетесь использовать его для 9 значащих цифр, и это не гарантированно доступны. Вы можете увидеть это очень легко, без разбора: (. «Г» является «туда-обратно» формат спецификатора)
float f = 333333333f;
Console.WriteLine("{0:r", f); // Prints 333333344
Другими словами, самое близкое float
значение точного десятичного значения 333333333 is 333333344.
Если бы вы использовали Double
, это, вероятно, сохранило бы все цифры, но это не значит, что это правильный подход. Это зависит от значения. Действительно ли это всегда целое число? Возможно, вы должны использовать long
. Это нецелые, но финансовые данные (или какое-то другое «искусственное» значение)? Если да, рассмотрите возможность использования decimal
.
Кроме того, почему вам нужно преобразовать это в строку и проанализировать ее? Каков тип времени выполнения dr["NationalTotal"]
? Вы можете просто бросить - избегайте использования конверсий строк, в которых вам не нужно.
его переход от преобразования сетки excel к datatable с использованием IExcelDataReader DataSet AsDataSet(); ... Я предположил, что все ячейки были строками .. может быть, я ошибаюсь .. плохой check – punkouter
ой .. вы правы .. это на самом деле [System.RuntimeType] = {Name = "Double" FullName = "System.Double"} ... но мне нужно преобразовать это в float .. – punkouter
@punkouter: Если вам нужно преобразовать в 'float', float' не имеет столько информации, сколько вам нужно, у вас проблемы. Но вы можете просто сбрасывать: 'var x = (float) (double) dr [" NationalTotal "];' - вам нужно бросать дважды, потому что приведение к 'double' просто распаковывается. –
Вы не должны вызывать 'ToString()'. (это ничего не исправит) – SLaks
Мне нужно это в поплавке поплавать nationalTotal = dr ["NationalTotal"]. ToString(). Trim() == ""? 0.0f: Convert.ToSingle (dr ["NationalTotal"]. ToString()); – punkouter
Сравните с 'DBNull.Value' не пустую строку. – Romoku