Страницы: 1
RSS
Round не округляет или Int не даёт целое?
 
Столкнулся с ситуацией когда целую часть числа нужно обрабатывать от дробной, написал функцию и заметил, что результат получается с кучей знаков после точки, т.е. вместо 6.1 получается 6.09999990463256 напихал в функцию Round где нужно и где не нужно - результат тот же. Так и не могу понять где собака порылась.
Набросал пример функции где сначала складываются целые части чисел, потом дробные только два знака преобразуются в целые (умножением на 100), складываются между собой, результат делится на сто и прибавляется к сумме целых частей. Получилась такая же фигня. В примере просто складывал число с одним знаком после точки с нулём и смотрите что получилось.
Не стреляйте в тапера - он играет как может.
 
Однако Debug показывает правильно...
 
single на Double поменяйте и будет счастье
Изменено: Ivan.kh - 09.07.2016 20:01:35
 
Ivan.kh, спасибо, а почему так происходит? Ведь single от double по идее различаются только допустимым диапазоном. Мне по идее даже single много :)
Хотя я подозревал что что-то с типом и пробовал без явного указания типа, но результат не менялся, т.е. получается что эксель по умолчанию считал тип как single.
Не стреляйте в тапера - он играет как может.
 
Ts.Soft, если макрос должен работать с данными для Excel листа, то всегда нужно использовать тип Double, т.к. в Excel для чисел используется тип Double. Иначе Ваш макрос будет давать одни результаты, а Excel другие.
Single и Double отличаются внутренним механизмом. Этот механизм сложен для нематематиков, поэтому понять этот механизм не каждый сможет сходу. При конвертации числа из Single в Double и обратно сами числа могут изменяться. В этом примере в переменной "dblNumber" уже будет не 1,1, а  1,10000002384186:
Код
Sub Макрос1()
    Dim sngNumber As Single, dblNumber As Double
    sngNumber = 1.1
    dblNumber = sngNumber
End Sub
 
Karataev, спасибо
Не стреляйте в тапера - он играет как может.
 
После исправления Single на Double всё стало вроде бы нормально, но обнаружил, что 0.29+0.01=0.29 и ещё много подобных примеров.
Начал смотреть через отладчик - kib,rf в строке
Код
a_d = Int(Round((a - Int(a)), 2) * 100)
и возникает после выполнения последнего Int, т.е. вариант
Код
a_d = Round((a - Int(a)), 2) * 100
даёт правильный результат. Round тоже можно убрать - первоначально его не было, вставил когда пытался убрать лишние знаки).
Видимо Int отбрасывает дробную часть каким-то хитрым способом из высшей математики, возможно используя теорему Ферма :)
Изменено: Ts.Soft - 10.07.2016 07:23:57
Не стреляйте в тапера - он играет как может.
 
Цитата
Ts.Soft написал:
обнаружил, что 0.29+0.01=0.29
у меня VBA выдает 0,3. Предположу, что Вы сделали какую-то ошибку во время тестирования.
 
Karataev, у Вас в обоих столбцах 0.3?
 
Не стреляйте в тапера - он играет как может.
 
Я имел ввиду, что не Ваш макрос, а вообще VBA выдает результат 0,3. Ваш макрос я не смотрел.

Цитата
Karataev написал: Round тоже можно убрать
уберите Round, если Вы не будете его использовать, и заново вставьте файл на форум. Зачем форумчанам смотреть макрос, который Вы не будете использовать.

И опишите словами, что должна делать Ваша функция.
Изменено: Karataev - 10.07.2016 11:27:35
 
Цитата
Karataev написал:
Зачем форумчанам смотреть макрос, который Вы не будете использовать
Именно этот макрос я использовать не буду, просто есть задача когда целые части  дробные нужно обрабатывать отдельно, вот и набросал пример для себя. Сначала вылезли лишние знаки после точки, но с этим разобрались, далее при тестировании обнаружил что из-за лишней Int результат получается неверный. Вот мне и непонятно почему Int обрабатывая заведомо целое число уменьшил его.
если взять строку
Код
a_d = Int((a - Int(a)) * 100)
где a изначально имеет не более двух десятичных разрядов и пошагово вычислить , то при a=0.29 (b при многих других) получается что последняя Int уменьшает значение на единицу. Если добавить в функцию строку
Код
Debug.Print a, Int(a), a - Int(a), (a - Int(a)) * 100, Int((a - Int(a)) * 100)
то результат в окне Immediate будет таким:
Код
 0.29          0             0.29          29            28 
получается что
Код
Int((0.29 - Int(0.29)) * 100) ->
Int((0.29 - 0) * 100) ->
Int(0.29 * 100) ->
Int(29) ->
28
Вот мне и непонятно почему так происходит и хотелось бы разобраться чтобы в будущем быть готовым к такому поведению Int.
Не стреляйте в тапера - он играет как может.
 
Цитата
Ts.Soft написал:
Именно этот макрос я использовать не буду,
тогда и не нужно на форуме выкладывать макрос, а сформулируйте вопрос без показа своего макроса.
 
Karataev, Вы не правы, т.к. я буду использовать не именно этот макрос, а тот из которого он был получен - в исходной функции есть дополнительные строки которые к делу не относятся (хотя она тоже ещё далеко не окончательная).
Мне не нужно готовое решение моей задачи, я просто хочу понять почему при некоторых значениях a, например 0.29, 0.57, 0.58, 1.13, 1.14
Код
Int((a - Int(a)) * 100) <> (a - Int(a)) * 100
Не стреляйте в тапера - он играет как может.
 
Ну так опишите словами, что должна делать эта функция, которую Вы показываете на форуме.
 
Karataev, функция должна отделить дробную часть от целой и превратить её в целое число, например из длины метры.сантиметры выделить сантиметры или из рубли.копейки выделить копейки, т.е 0.29 преобразовать в 29. Вопрос почему строка
Код
(a - Int(a)) * 100
из 0.29 делает 29, а строка
Код
Int((a - Int(a)) * 100)
из 0.29 делает 0.28. Хотя при этом большинство других исходных данных дают одинаковый результат

Мне не нужен совет пользоваться первым вариантом и не заморачиваться, мне не нужно предлагать друге варианты отделения рублей от копеек, сантиметров от метров, килограммов от центнеров и т.д.. Мне нужно понять почему так происходит именно в этом примере..
Изменено: Ts.Soft - 10.07.2016 10:45:13
Не стреляйте в тапера - он играет как может.
 
Сначала функция должна сложить два числа, а затем в полученной сумме функция должна выделить дробную часть и превратить дробную часть в целое число?
 
Достаточно только
Цитата
Karataev написал: выделить дробную часть и превратить дробную часть в целое число
Но мне важно понять почему в моём примере использование дополнительной (лишней) Int в некоторых случаях уменьшает результат на единицу
Не стреляйте в тапера - он играет как может.
 
Ну тогда измените Вашу функцию и заново вложите на форуме. Зачем Вы нам показываете то, чего не нужно?
В Вашей функции ведь происходит сложение сначала.
Страницы: 1
Читают тему
Наверх