Непонятка какая-то с децимал.
такой простой код но не могу получить точность 5 знаков после запятой
decimal a = (считывается из базы и в переменной находится значение) 83.90080;
decimal b = (считывается из базы и в переменной находится значение) 83.90080;
var result = Dceimal.Round(Decimal.Divide(a, b), 5)
= 1
а надо 1.00000
как получить 5 знаков без умножения результата деления на 1.00000m?
Здравствуйте, peer, Вы писали:
P>decimal a = (считывается из базы и в переменной находится значение) 83.90080; P>decimal b = (считывается из базы и в переменной находится значение) 83.90080; P>var result = Dceimal.Round(Decimal.Divide(a, b), 5)
P>= 1 P>а надо 1.00000
Для decimal 1 и 1.00000 это в точности одно и то же.
Ты, наверное, хочешь чтобы в выводе на экран было 1.00000? Но это просто строковое представление. Так что надо задать правило форматирования в строку:
Здравствуйте, peer, Вы писали:
P>Непонятка какая-то с децимал. P>= 1 P>а надо 1.00000
Это потому что decimal это floating point, а ты, похоже, ожидаешь fixed point. Погляди в сторону SqlDecimal:
Здравствуйте, ·, Вы писали:
P>>Непонятка какая-то с децимал. P>>= 1 P>>а надо 1.00000 ·>Это потому что decimal это floating point, а ты, похоже, ожидаешь fixed point. Погляди в сторону SqlDecimal:
Decimal это не floating point. У него как раз все ровно поделилось, и незначащие нули по умолчанию не выводятся (откуда знать что их надо ровно 5?)
Здравствуйте, fmiracle, Вы писали:
F>·>Это потому что decimal это floating point, а ты, похоже, ожидаешь fixed point. Погляди в сторону SqlDecimal: F>Decimal это не floating point. У него как раз все ровно поделилось, и незначащие нули по умолчанию не выводятся
За это минусы? Доки я тут один что-ли читаю?..
Decimal Struct — Represents a decimal floating-point number.
Здравствуйте, ·, Вы писали:
·>За это минусы? Доки я тут один что-ли читаю?.. ·>
Decimal Struct — Represents a decimal floating-point number.
Минусы тебе не за floating-point, а за то что те проблемы неточности представления вроде бы точных цифр, на которые ты намекаешь, это не из-за плавучей точки, а из-за того что в классических float/double число представленно в двоичном виде, и преобразование его в десятичный порождает иррациональные числа на ровном месте. Т.е. просто сохранив в float рациональное число, даже без каких либо операций, а потом прочитав его и преобразовав в десятичное, ты можешь получить число иррациональное.
Так вот, суть decimal как раз в том что оно представляется в памяти именно десятичным, поэтому если десятичное число рационально, но оно таковым и останется.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>·>За это минусы? Доки я тут один что-ли читаю?.. НС>·>
Decimal Struct — Represents a decimal floating-point number.
НС>Минусы тебе не за floating-point, а за то что те проблемы неточности представления вроде бы точных цифр, на которые ты намекаешь,
Я ни на что не намекал. Я сказал, что если требуется фиксированное число знаков после запятой, то лучше использовать тип с фиксированной точкой, коим является SqlDecimal.
НС> это не из-за плавучей точки, а из-за того что в классических float/double число представленно в двоичном виде,
Про двоичный вид это вы сами придумали. В моём заминусованном сообщении не было ничего о двоичных.
НС> и преобразование его в десятичный порождает иррациональные числа на ровном месте. Т.е. просто сохранив в float рациональное число, даже без каких либо операций, а потом прочитав его и преобразовав в десятичное, ты можешь получить число иррациональное.
Причём тут иррациональные числа?!! Что-то тут похоже все всю школьную математику забыли.
НС>Так вот, суть decimal как раз в том что оно представляется в памяти именно десятичным, поэтому если десятичное число рационально, но оно таковым и останется.
Суть в том, что SqlDecimal тоже десятичное. Но не то же самое что Decimal struct.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
НС>>Минусы тебе не за floating-point, а за то что те проблемы неточности представления вроде бы точных цифр, на которые ты намекаешь, ·>Я ни на что не намекал. Я сказал, что если требуется фиксированное число знаков после запятой, то лучше использовать тип с фиксированной точкой
Нет, не лучше. И вопрос был вообще не про это.
·>, коим является SqlDecimal.
Серьезно? Использовать тип из пакетов драйвера для MSSQL?
НС>> это не из-за плавучей точки, а из-за того что в классических float/double число представленно в двоичном виде, ·>Про двоичный вид это вы сами придумали.
Это я не придумал, а пояснил, откуда странное поведение float типов и почему decimal этих проблем лишен.
НС>> и преобразование его в десятичный порождает иррациональные числа на ровном месте. Т.е. просто сохранив в float рациональное число, даже без каких либо операций, а потом прочитав его и преобразовав в десятичное, ты можешь получить число иррациональное. ·>Причём тут иррациональные числа?!!
При том что иррациональное число в обычных форматах потребует для хранения бесконечного объема памяти. Поэтому такое число округляется до ближайшего рационального. В результате двух неявных преобразований десятичное->двоичное->десятичное получаем ошибку и числа на выходе вроде 0.5999999986 вместо 0.6.
НС>>Так вот, суть decimal как раз в том что оно представляется в памяти именно десятичным, поэтому если десятичное число рационально, но оно таковым и останется. ·>Суть в том, что SqlDecimal тоже десятичное.
Суть в том что SqlDecimal это часть драйвера MSSQL, описывающая целевой тип decimal в нем. И в данном конкретном случае он полностью не нужен, так как и обычный дотнетный decimal будет вести себя точно так же. Вот правильный ответ — Re: Decimal.Divide
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Суть в том что SqlDecimal это часть драйвера MSSQL, описывающая целевой тип decimal в нем. И в данном конкретном случае он полностью не нужен, так как и обычный дотнетный decimal будет вести себя точно так же. Вот правильный ответ — Re: Decimal.Divide
Ну не совсем точно так же, есть небольшая разница. В SqlDecimal есть возможность указать положение точки явно через ConvertToPrecScale (потому что в sql server оно задается явным образом), а в дотнетном decimal оно всегда выбирается автоматически. Про это и говорит ·.
Только вот исходя из формулировки стартового топика, я не думаю, что топик-стартеру нужно было именно это. А тащить классы специфичные для mssql в несвязанные с ним задачи, даже если это студенческий практикум — бе.
Здравствуйте, fmiracle, Вы писали:
F>Здравствуйте, peer, Вы писали:
P>>decimal a = (считывается из базы и в переменной находится значение) 83.90080; P>>decimal b = (считывается из базы и в переменной находится значение) 83.90080; P>>var result = Dceimal.Round(Decimal.Divide(a, b), 5)
P>>= 1 P>>а надо 1.00000
F>Для decimal 1 и 1.00000 это в точности одно и то же.
F>Ты, наверное, хочешь чтобы в выводе на экран было 1.00000? Но это просто строковое представление. Так что надо задать правило форматирования в строку:
надо на фронт передавать 1.00000 чтобы фронт просто отображал
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>Минусы тебе не за floating-point, а за то что те проблемы неточности представления вроде бы точных цифр, на которые ты намекаешь, НС>·>Я ни на что не намекал. Я сказал, что если требуется фиксированное число знаков после запятой, то лучше использовать тип с фиксированной точкой НС>Нет, не лучше. И вопрос был вообще не про это.
Именно про это. Ему нужны числа с 5 знаками после запятой.
НС>·>, коим является SqlDecimal. НС> Серьезно? Использовать тип из пакетов драйвера для MSSQL?
Как я понял, топикстартер и так значения из базы берёт. Впрочем, как я понял, этот тип не из пакета драйверов MSSQL, а часть .net framework.
НС>>> это не из-за плавучей точки, а из-за того что в классических float/double число представленно в двоичном виде, НС>·>Про двоичный вид это вы сами придумали. НС>Это я не придумал, а пояснил, откуда странное поведение float типов и почему decimal этих проблем лишен.
Круто, конечно. Но это никакого отношения к обсуждаемой проблеме не имеет. Мы обсуждаем float-point vs fixed-point арифметику _десятичных_ чисел. Причём тут двоичные числа-то?!!
НС>>> и преобразование его в десятичный порождает иррациональные числа на ровном месте. Т.е. просто сохранив в float рациональное число, даже без каких либо операций, а потом прочитав его и преобразовав в десятичное, ты можешь получить число иррациональное. НС>·>Причём тут иррациональные числа?!! НС>При том что иррациональное число в обычных форматах потребует для хранения бесконечного объема памяти. Поэтому такое число округляется до ближайшего рационального. В результате двух неявных преобразований десятичное->двоичное->десятичное получаем ошибку и числа на выходе вроде 0.5999999986 вместо 0.6. Почитай что такое иррациональные числа. 1/3 — число рациональное, но непредставимо ни в виде десятичной записи, ни в виде двоичной, хотя не требует бесконечного объёма памяти, т.к. можно представить в троичной записи.
НС>>>Так вот, суть decimal как раз в том что оно представляется в памяти именно десятичным, поэтому если десятичное число рационально, но оно таковым и останется. НС>·>Суть в том, что SqlDecimal тоже десятичное. НС>Суть в том что SqlDecimal это часть драйвера MSSQL, описывающая целевой тип decimal в нем.
Есть два типа арифметики "fixed point" и "float point" и есть два типа представления чисел binary и decimal. И возможны все четыре комбинации. Можно такую табличку составить:
Fixed-point
Float-point
decimal
SqlDecimal
decimal struct
binary
not in .net
float, double
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, peer, Вы писали:
P>как получить 5 знаков без умножения результата деления на 1.00000m?
А попробуй так
var result = 0.00000m;
result = Dceimal.Round(Decimal.Divide(a, b), 5);
Здравствуйте, peer, Вы писали:
P>надо на фронт передавать 1.00000 чтобы фронт просто отображал
Передавай на фронт строку. Браузеры тоже не умеют в fixed point, надо будет самому реализовывать или либу какую-нибудь искать.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Это я не придумал, а пояснил, откуда странное поведение float типов и почему decimal этих проблем лишен.
Кстати, не лишен. decimal тоже теряет точность:
var n = "1000000000000000000000000.00001";
var flt = decimal.Parse(n);
var fxd = SqlDecimal.Parse(n);
Console.WriteLine(flt);// выводит 1000000000000000000000000.0000
Console.WriteLine(fxd);// выводит 1000000000000000000000000.00001
float типы по определению теряют точность. Просто double теряет двоичные знаки, а decimal — десятичные.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
НС>>Это я не придумал, а пояснил, откуда странное поведение float типов и почему decimal этих проблем лишен. ·>Кстати, не лишен. decimal тоже теряет точность:
Он теряет ее предсказуемым и очевидным образом.
·>float типы по определению теряют точность.
Любой тип теряет точность, в том числе и fixed point.
·> Просто double теряет двоичные знаки, а decimal — десятичные.
Еще раз — проблема не в этом. Проблема в том, что если мы возьмем число, которое в десятичном представлении содержит заведомо меньшее количество знаков, чем точность, потом сохраним его в float, а потом опять получим десятичное представление, то результат может отличаться. А вот в decimal такой ситуации не будет, не смотря на то что точка там плавающая. А в исходном примере плавающая точка или нет — вообще все равно, потому что там нигде не происходит плаванья той самой точки.