Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - .NET

Страница: 1 | 2 |

 

  Вопрос: Округление Добавлено: 15.02.09 19:08  

Автор вопроса:  -=Fenix=-
Dim a As Single
Dim b As Single
Dim c As Single

a = Convert.ToString("1,2898")
b = Convert.ToString("1,2891")
c = a - b
MsgBox(c)


результат должен быть 0,0007, но как нистарнно он равен 0,00069999969

Почему так? и как можно сделать чтоб точно выводилось без округлений и разложений?

Ответить

  Ответы Всего ответов: 23  

Номер ответа: 1
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #1 Добавлено: 15.02.09 19:38
0,0007 на самом деле очень близко к 0,00069999969 :)

Это связано с особенностями обработки чисел с плавающей запятой. Без округлений от этой особенности избавиться не получится.

Если хочешь, попробуй воспользоваться типом Decimal.

Ответить

Номер ответа: 2
Автор ответа:
 AWP



ICQ: 345685652 

Вопросов: 96
Ответов: 1212
 Web-сайт: xawp.narod.ru
 Профиль | | #2
Добавлено: 16.02.09 00:01
Используй тип Double
  1. Dim a As Double
  2. Dim b As Double
  3. Dim c As Double

Ответить

Номер ответа: 3
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #3 Добавлено: 16.02.09 00:50
AWP, Double здесь никаким образом не поможет, так как это тоже число с плавающей запятой и работает точно также как и Single

Что касается топик-стартера, сейчас вчитался в код и понял насколько сильно он отжог!

1)
  1. a = Convert.ToString("1,2898")

Вдумайся - ты конвертируешь строку (тип String) в ту же самую строку (ToString возвращает String)! А потом полученный String приравниваешь к переменной типа Single :)

Вместо этого нужно просто написать:
  1. a = 1.2898


Или можно сделать это даже в строчке где ты объявляешь переменную:
  1. Dim a As Single = 1.2898


2) В коде у тебя жестко прописана строка - "1,2898". Всвязи с этим есть одна очень серьезная проблема - работа этого кода зависит от того, что написано у пользователя в региональных настройках Windows. У меня например в Windows американские региональные настройки, а в этом формате десятичный разделитель - не "," а ".". Следовательно, твой код работает на моем компьютере некорректно.

3) Функция MsgBox устарела, в .NET вместо нее нужно использовать MessageBox.Show, Console.WriteLine, Response.Write, в зависимости от того, какой тип приложения ты разрабатываешь.

Вобщем вот корректно рабочий код, который не приводит к ошибкам округления:

  1.         Dim a As Decimal
  2.         Dim b As Decimal
  3.         Dim c As Decimal
  4.  
  5.         a = 1.2898D
  6.         b = 1.2891D
  7.         c = a - b
  8.         Console.WriteLine(c)


-=Fenix=- , не обижайся, но ты, видимо, только недавно сел за .NET, причем до этого имел обильный опыт работы с VB6, и поэтому не совсем корректно используешь возможности этой платформы.
Ничего страшного в этом нет, советую просто прочитать несколько книг, которые бы описывали платформу .NET и особенности работы с ней.

Ответить

Номер ответа: 4
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #4 Добавлено: 16.02.09 00:52
Да еще забыл добавить. Судя по всему ты работаешь с отключенной опцией жесткой проверки типов. Эту опцию обязательно нужно включить, она позволяет избежать большого количества ошибок, связанных с приведением типов.

Для этого в самом вверху файла нужно написать
  1. Option Strict On


Или же в свойствах проекта включить глобально эту опцию. Также ее можно включить в свойствах Visual Studio, и тогда все новые проекты будут работать с жесткой проверкой типов по умолчанию.

Ответить

Номер ответа: 5
Автор ответа:
 Mutalisk



ICQ: 364366445 

Вопросов: 4
Ответов: 11
 Профиль | | #5 Добавлено: 16.02.09 06:48
  1. Dim Summa As String
  2. Dim Result As String
  3. Result = Format(Val(Summa), "#.00")


Вот так можно округлить.

Ответить

Номер ответа: 6
Автор ответа:
 fAndOrIn



Вопросов: 5
Ответов: 344
 Профиль | | #6 Добавлено: 16.02.09 08:00
Mutalisk, в данном случае при точности даннных до 1/10000 правильнее было бы Format(csng("1,2898";)-csng("1,2891";), "0.0000";)

Ответить

Номер ответа: 7
Автор ответа:
 fAndOrIn



Вопросов: 5
Ответов: 344
 Профиль | | #7 Добавлено: 16.02.09 08:17
А по большому счёту, если бы у человека было 16 пальцев (а лучше 2), мы бы сейчас не маялись с подобными проблемами!

Ответить

Номер ответа: 8
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #8 Добавлено: 16.02.09 11:57
Иногда у меня возникает подозрение что надо мной кто-то стебется...

Mutalisk, String - это не число а строка. Можешь пояснить в чем глубокий смысл хранения числа с плавающей запятой в строковой переменной, а потом двойное преобразование в число и в строку?

fAndOrIn #6, двумя постами выше я писал почему не стоит делать так как сделал ты.

fAndOrIn #7, если бы у отдельных представителей человечества были мозги, то подобными вопросами задаваться не пришлось бы

Ответить

Номер ответа: 9
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #9 Добавлено: 16.02.09 12:36
Mutalisk #5 - чушь полная(юзать Val в NET - некорректно)
fAndOrIn #6 - чушь полная(для округления стоит использовать Math.Round)

Option Strict On

Steel Brand +1

a = Convert.ToString("1,2898";)

вот за это вот я и ненавижу VB! За вот это вот издевательство над типами... В результате его самостоятельных приведений "программисты" позволяют себе писать подобную ахинею, а компилятор это проглатывает..

Ответить

Номер ответа: 10
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #10 Добавлено: 16.02.09 12:40
аффтару срочно читать раздел любой книге где рассказывается о типах данных!!

Ответить

Номер ответа: 11
Автор ответа:
 fAndOrIn



Вопросов: 5
Ответов: 344
 Профиль | | #11 Добавлено: 16.02.09 12:54
Иногда у меня возникает подозрение что надо мной кто-то стебется...
? Пожалуй,
если бы у отдельных представителей человечества были мозги, то подобными вопросами задаваться не пришлось бы
Steel Brand @ EROS, я всего лишь дал свой комментарий на Mutalisk #5
А что конкретно хочет получить афтар - строку(Format) или число(Round), решать не вам!

Ответить

Номер ответа: 12
Автор ответа:
 fAndOrIn



Вопросов: 5
Ответов: 344
 Профиль | | #12 Добавлено: 16.02.09 13:13
А если кто-то считает, что десятичная система - самое удачное "изобретение" человечества, то это его проблема. Заметьте, я при этом не перехожу на личности...

Ответить

Номер ответа: 13
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #13 Добавлено: 16.02.09 13:18
я всего лишь дал свой комментарий на Mutalisk #5

ну так будь добр давай корректный комментарий а не нести чушь . Функция Format,которую ты используешь, это рудимент VB6 так же как CSng!!
Для форматирования числа в строку в NET надо использовать либо метод ToString() с параметрами, либо String.Format.
Подробнее о методах форматировании узнаешь в MSDN. А для приевдения строки к нужному типу надо испозовать метод Parse соответствующего типа.. например Single.Parse("1.00214";)

А если кто-то считает, что вправе давать некорректные советы используя рудиментарные функции отсталого языка, то это его проблема.
Заметьте, я при этом не перехожу на личности...

Ответить

Номер ответа: 14
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #14 Добавлено: 16.02.09 13:34
fAndOrIn, вне зависимости от того что хочет получить автор, ваши ответы недостаточно корректны по сравнению с моими :)

Ответить

Номер ответа: 15
Автор ответа:
 fAndOrIn



Вопросов: 5
Ответов: 344
 Профиль | | #15 Добавлено: 16.02.09 13:53
Щас заплачу: vb6-отстой, NET-КРУТИЗНА!!!
Для особо одаренных еще раз попробую на слогах объяснить, что влез в этот базар только после того, как увидел 'дельное' предложение
  1. Dim Summa As String
  2. Dim Result As String
  3. Result = Format(Val(Summa), "#.00")
,явно на NET состряпанное и не смог пройти мимо (в чем искренне раскаиваюсь).

Ответить

Страница: 1 | 2 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам