Форум: "Основная";
Текущий архив: 2003.11.27;
Скачать: [xml.tar.bz2];
ВнизКак округлить дробное число с 3-х занков до 2-х после запятой? Найти похожие ветки
← →
Developerr (2003-11-16 19:58) [0]Извиняюсь за не очень умный вопрос, но, что вылетело...
Подскажите, пожалуйста, как округлить в Delphi дробное число с 3-х занков до 2-х после запятой? Например, 2958,375 до 2958,38.
Спасибо.
← →
Cr@sh (2003-11-16 19:59) [1]uses Math
RoundTo();
← →
Developerr (2003-11-16 20:14) [2]Спасибо, но эта функция по-моему с глюками. Как объяснить, что она округляет число 2958,375 до 2958,37, а не 2958,38? А число 1.245 округляет нормально. Хотя, если добавить впереди еще единичку 11.245 получится 11.24 ???
Может есть какой-то секрет?
Спасибо.
← →
Думкин (2003-11-16 20:18) [3]Секрет этот тут каждый день раскрывается.
Нужно только взглянуть на код этой функции, а потом в хелпе прочитать про Round, только до конца.
Вот и весь секрет.
← →
Anatoly Podgoretsky (2003-11-16 20:23) [4]У тебя не это число, тебе только кажется
← →
Лена (2003-11-16 20:32) [5]нужно число открыть как стринг и срезать последний символ
так пойдет ?
← →
Developerr (2003-11-16 20:45) [6]Expression Value
RoundTo(1234567, 3) 1234000
RoundTo(1.234, -2) 1.23
RoundTo(1.235, -2) 1.24
RoundTo(1.245, -2) 1.24
Note: The behavior of RoundTo can be affected by the Set8087CW procedure or SetRoundMode function.
Хрень какая-то.
Кстати, RoundTo(1.245, -2)=1.25, а не 1.24. Не глюк? Глюк. Вы попробуйте эти примеры...
> Anatoly Podgoretsky
> У тебя не это число, тебе только кажется
Самому хоть понятна эта формулировка?
Кто-нибудь может дать дельный совет, а лучше пример?
← →
Иван Шихалев (2003-11-16 20:50) [7]> Как объяснить, что она округляет число 2958,375
> до 2958,37, а не 2958,38?
2958.375 округляется до 2958.38, см. Help
← →
Лена (2003-11-16 20:53) [8]Developerr >
пример с обризанием последнего символа выложить ?
← →
Alexious (2003-11-16 20:55) [9]n:=2958.375;
n:=Round(n*100)/10;
:)))
← →
Alexious (2003-11-16 20:58) [10]
n:=2958.375;
n:=Round(n*100)/10;
:))
← →
sniknik (2003-11-16 21:02) [11]Developerr © (16.11.03 20:45) [6]
бугалтерское округление, слышал о таком? более правильное при больших последовательностях округляемых чисел (и суммировании) чем школьное математическое. т.что это не глюк.
> Кто-нибудь может дать дельный совет, а лучше пример?
а совет ты сам сюда привел, только не обратил внимания
> Note: The behavior of RoundTo can be affected by the Set8087CW procedure or SetRoundMode function.
т.е. вызов SetRoundMode(rmNearest); перед RoundTo решит твою проблему(??).
кстати у меня по умолчанию так стоит (зависит от конкретного сопроцессора?)
← →
Alexious (2003-11-16 21:03) [12]
n:=2958.375;
n:=Round(n*100)/10;
:))
← →
Anatoly Podgoretsky (2003-11-16 21:07) [13]Developerr © (16.11.03 20:45) [6]
Очень даже понятна, а тебе, раз у тебя это вызвало удивление.
← →
Developerr (2003-11-16 21:08) [14]
> Лена
Мне нужно не просто обрезать, а округлить. Если вы это имели ввиду, тогда выложите, пожалуйста.
> Иван Шихалев ©
Где смотреть в Help"e?
Я пробую так:ShowMessage(FloatToStr(RoundTo(2958,375)));
или так:
n:=RoundTo(2958,375);
ShowMessage(FloatToStr(n));
Получается 2958,37 и все тут.
← →
Zmei (2003-11-16 21:12) [15]Так попробуй ShowMessage(floattostr(Round(3958.37*100)/10));
← →
Developerr (2003-11-16 21:13) [16]
> Anatoly Podgoretsky
Мне нет!!!
> Alexious ©
> n:=2958.375;
> n:=Round(n*100)/10;
> :))
Это что? Тут совсем не то.
← →
Developerr (2003-11-16 21:17) [17]
> Zmei
Причем тут это
> Так попробуй ShowMessage(floattostr(Round(3958.37*100)/10));
Мне нужно из 2958.375 получить 2958.38.
← →
Фдучшщгы (2003-11-16 21:29) [18]>Developerr © (16.11.03 21:17) [17]
Ну и че эта штука же работает . ты хоть пробовал
Делай так
ShowMessage(floattostr((Round(3958.375*100))/10));
и все будет ништяк
← →
Developerr (2003-11-16 21:34) [19]
> Фдучшщгы
Вы что издеваетесь? Вы пробовали использовать то что написали???
В результате получается - 39583,8
> sniknik ©
Пробовал писать так:
SetRoundMode(rmNearest);
ShowMessage(FloatToStr(RoundTo(2958,375)));
Все одно - 2958,37
:-(((((
← →
Alexious (2003-11-16 21:48) [20]Ну подправил бы. Ошибся
ShowMessage(floattostr((Round(3958.375*100))/100));
← →
Developerr (2003-11-16 21:56) [21]
> Alexious ©
Спасибо. Получилось.
← →
sniknik (2003-11-16 22:28) [22]Developerr © (16.11.03 21:34) [19]
> Пробовал писать так:
> SetRoundMode(rmNearest);
> ShowMessage(FloatToStr(RoundTo(2958,375)));
> Все одно - 2958,37
там еще 3 параметра осталось попробуи их чтоли.
но вообще SetRoundMode както там странно вычисляет (и видать неправильно), маленькие числа правильно округляет а вот 2958,375 какоето "волшебное" ;о)).
установи напрямую для гарантии
Set8087CW($1B72);
ShowMessage(FloatToStr(RoundTo(2958,375)));
у меня срабатывает.
← →
Иван Шихалев (2003-11-16 22:55) [23]> 2958,375 какоето "волшебное" ;о)).
Гм... Т.е. округялет и не к ближайшему и не к четному? Оригинально. Delphi нет, проверить не могу... Если это число действительно такое волшебное, то дело во внутреннем представлении... Может помочь замена типа, особенно - в сторону большей точности.
← →
sniknik (2003-11-16 23:07) [24]> Может помочь замена типа, особенно - в сторону большей точности.
если дело было в разрядности сетки(т.е. представление не 2958,375 а 2958,374915.... ну как обычно) то по идее и Set8087CW($1B72); не помогло бы (даже по школьному тогда былобы ...2958,37)
а может это учитывается в параметре $1B72 а тот что вычисляется в SetRoundMode этого не учитывает (ведь в итого тоже Set8087CW вызывается только с другим параметром).
← →
Иван Шихалев (2003-11-16 23:19) [25]> не помогло бы
Не факт. Все эти фокусы с плавающей точкой - тот еще лабиринт. Доки жаль под рукой нет по режимам сопроцессора... Кроме того, если число не вводится ручками, а вычисляется, то одна и та же операция может возвращать как 0.24992, так и 0.25001 (цифры взяты от балды).
← →
Иван Шихалев (2003-11-16 23:19) [26]В смысле - одна операция при разной размерности.
← →
Думкин (2003-11-17 05:37) [27]> [20] Alexious © (16.11.03 21:48)
Ровно так и работает RoundTo. :-(
> [25] Иван Шихалев © (16.11.03 23:19)
Скорее всего дело в этом. Поэтому и разница в
> А число 1.245 округляет нормально. Хотя, если добавить впереди
> еще единичку 11.245 получится 11.24 ???
все-такки плавающая точка - она и есть плавающая точка.
← →
sniknik (2003-11-17 08:14) [28]Иван Шихалев © (16.11.03 23:19) [25]
Думкин © (17.11.03 05:37) [27]
доки нет да жаль.
а зависит ли от числа? скорее всего режим неправильный какойто устанавливается
посмотрел
в SetRoundMode вычисляется и устанавливается Set8087CW( $31С4), чего этим делается и этого ли добится хотели?, чего в хелпе
rmNearest Rounds to the closest value.
ведь с ручным вводом режима Set8087CW($1B72) работает правильно.
← →
BlackTiger (2003-11-17 10:49) [29]2 sniknik: бугалтерское округление, слышал о таком
нет такого округления, есть банковское, т.е. округление до ближайшего четного. Насколько я знаю - почти нигде не используется, т.к. очень усложняет расчеты.
Блин, народ! Че флейм разводить по такому дурацкому вопросу? Вы в школе нормально учились?
Берем 33.12 482, а точнее 33.12 482).
Округление до 2х знаков даст 33.12, так как 482 < 500 (точнее 4 < 5).
Огругление до 3х знаков даст 33.125, так как 82 > 50 (точнее 8 > 5).
Вот и все округление. Все остальное - от лукавого!
← →
Anatoly Podgoretsky (2003-11-17 11:15) [30]BlackTiger © (17.11.03 10:49) [29]
Насчет нигде, ты очень, очень преувеличил.
И на школу не надо бочку катить.
← →
Семен Сорокин (2003-11-17 11:18) [31]2All
Каждый раз одно и тоже.
ЗЫ
Если один раз - случайность, два - совпадение, а три - диагноз. :)
(С)
← →
Думкин (2003-11-17 11:32) [32]
> [30] Anatoly Podgoretsky © (17.11.03 11:15)
Фууу, а я думал опять кровью завоняло, а стоит ли?
← →
Anatoly Podgoretsky (2003-11-17 11:36) [33]Пусть живет.
← →
Silver Alex (2003-11-17 11:40) [34]
> BlackTiger © (17.11.03 10:49) [29]
> 2 sniknik: бугалтерское округление, слышал о таком
> нет такого округления, есть банковское, т.е. округление
> до ближайшего четного. Насколько я знаю - почти нигде не
> используется, т.к. очень усложняет расчеты.
ну попробуй для эксперимента
Round(12,5) равно 12
а Round(13,5) равно 14
то же и с RoundTo
страно правда? но это и есть бугалтерское округление о котором сразу сказал sniknik ©
← →
Anatoly Podgoretsky (2003-11-17 11:46) [35]Silver Alex © (17.11.03 11:40) [34]
Не странно, а вполне нормально, а еще более нормально использовать то округление, которое нужно для задачи, а их не одно и не два.
← →
Developerr (2003-11-17 12:01) [36]
> sniknik ©
> ведь с ручным вводом режима Set8087CW($1B72) работает правильно.
Для этого случая правильно. А если взять число, скажем 2958,30 и посмотри, что получится. А получится 2958,31. Раззве это правильно? На мой взгляд самое правильное решение:
> ShowMessage(floattostr((Round(3958.375*100))/100));
Работае четко и во всех случаях.
← →
sniknik (2003-11-17 12:14) [37]какая разница как назвать. тут уже дело в другом
читаем хелп
у раундов
Note: The behavior of Round can be affected by the Set8087CW procedure or SetRoundMode function.
т.е. или то или то.
у SetRoundMode
rmNearest Rounds to the closest value.
т.е. к ближайшему значению.
а на практике видим другое (хотя правильного поведения добится не проблема) но почему написаное в хелпе не срабатывает (глюк дельфей? или неправильный перевод?)
вот что странно. а не уже действительно надоевшее обсуждение одного и тогоже (сктати замедтье и отмазки тоже похожие, и уже надоевшие)
> BlackTiger © (17.11.03 10:49) [29]
> Насколько я знаю - почти нигде не используется, т.к. очень усложняет расчеты.
сказал бы ты это нашему бугалтеру, она бы тебя порвала как бобик жучку. ;о))
кроме шуток у нее и с этим по округлениям до ста руб. набегает (плюса а для нее это недостача) с математическим раз в 20 возрастет.
← →
sniknik (2003-11-17 12:21) [38]Developerr © (17.11.03 12:01) [36]
нда... уж. действительно.
срочно нужна дока по режимам сопроцессора!! :о))
← →
sniknik (2003-11-17 12:37) [39]Developerr © (17.11.03 12:01) [36]
> Работае четко и во всех случаях.
во всех ли?
посмотри на функцию RoundTo, ничего знакомого не видиш? только тут обратные операции LFactor получается 0.01
function RoundTo(const AValue: Double; const ADigit: TRoundToRange): Double;
var
LFactor: Double;
begin
LFactor := IntPower(10, ADigit);
Result := Round(AValue / LFactor) * LFactor;
end;
деление на 0.01 = умножению на 100 и наоборот.
кстати похоже в этом и есть ошибка дельфей (алгоритм), они работают с дробными числами, плодят т.к. сказать ошибку, ведь чем меньше числа тем больше погрешностей в разрядной сетке можно словить, не. а установка режима вовсе не причем. (?)
← →
Anatoly Podgoretsky (2003-11-17 12:40) [40]sniknik © (17.11.03 12:21) [38]
На сайте Интела
sniknik © (17.11.03 12:37) [39]
Тут происходит много преобразований, и на каждом возможна ошибка представления.
← →
Developerr (2003-11-17 12:57) [41]Я уже совсем запарился. Снова глюк.
ShowMessage(FloatToStr((Round(1.625*100))/100));
Округляет до 1.62, а надо 1.63. Хотя, если взять 1.615 или 1.635 округляет как положено. Кошмар :-(((((
← →
Anatoly Podgoretsky (2003-11-17 13:06) [42]Округлило правильно, до четного.
← →
Developerr (2003-11-17 13:08) [43]Тупые Америкозы, в паскале все работает тип топ.
просто пишем
a:=1.625;
writeln(a:2:2);
И все рабоает. Неужели нельзя было сделать и Delphi тоже самое???
Может есть все-таки что-то подобное?
← →
Anatoly Podgoretsky (2003-11-17 13:13) [44]Да и 1,615 округлило до 1,61 тоже правильно, поскольку 1,615 невожможно представить, а правильное представление такое 1,61499999999999999
Ты зря не пислушался к моему замечанию Anatoly Podgoretsky © (16.11.03 20:23) [4]
При работе с плавающей запятой надо учитывать, что в отличии от фиксированой запятой, точность не абсолютная, а относительная.
← →
Developerr (2003-11-17 13:13) [45]
> Anatoly Podgoretsky
Нафига мне до четного? Мне нужно правильно, а не до четного. Сказать преподавателю матеметики, что если округлить число 1.625 до 2-х знаков после запятой получится 1.62. Он и поставит оценку ту которая стоит в конце числа - 2.
← →
Anatoly Podgoretsky (2003-11-17 13:14) [46]А конечно, враги виноваты :-)
← →
Anatoly Podgoretsky (2003-11-17 13:16) [47]Developerr © (17.11.03 13:13) [45]
Так почему ты тогда пользуешься функцией, которая округляет до четного? Не нравится сделай свою, по своим правилам.
А твое правильно, не более правильно, чем другие методы округления, не будь ежиком.
← →
sniknik (2003-11-17 13:24) [48]Developerr © (17.11.03 13:13) [45]
> Нафига мне до четного?
как математическое включается я уже показывал. попробуй с ним и со свои RoundTo.
← →
IgAn (2003-11-17 13:40) [49]2Developper
Trunc(2958,375 * 100 + 0.5)/100
делает именно то, что тебе нужно.
← →
Developerr (2003-11-17 13:44) [50]Короче, пробовал все. Ничего не работает. Буду думать что-то еще.
> Anatoly Podgoretsky ©
> Да и 1,615 округлило до 1,61 тоже правильно, поскольку 1,615
> невожможно представить, а правильное представление такое
> 1,61499999999999999
Фигня это все. Паскаль и фокс под ДОС считают по человечески, а такая срань как Делфи пургу несет. Не зря задорнов про Америкоз говорит: НУ ТУПЫЕ.
← →
Anatoly Podgoretsky (2003-11-17 13:46) [51]У тебя что ни будь еще есть, кроме тупые?
← →
Danilka (2003-11-17 13:48) [52][50] Developerr © (17.11.03 13:44)
точно! советую срочно переходить на паскаль и фокс под дос. и при запуске программы обязательная заставка со словами задорнова.
← →
Developerr (2003-11-17 13:55) [53]
> IgAn ©
Спасибо. Помогло. Пока глюков не выявил.
> Anatoly Podgoretsky ©
Конечно есть. Ну, об этом не будем.
> Danilka ©
Просто 5 баллов. Мне очень понравилось. Спасибо. А ты не Андрей Данилка, который Верку Сердючку играет?
← →
Anatoly Podgoretsky (2003-11-17 14:03) [54]Ну, ну, не поленись проверить.
D := 1.615;
D1 := Trunc(D * 100 + 0.5)/100;
ShowMessage(FloatToStr(D1));
ShowMessage(FloatToStr(Trunc(1.615 * 100 + 0.5)/100));
У тебя огромная дыра в понимании чисел с плавающей запятой
← →
IgAn (2003-11-17 14:17) [55]
> Anatoly Podgoretsky © (17.11.03 14:03) [54]
> Ну, ну, не поленись проверить.
Я не поленился, ты тоже не поленись...
D := 1.615;
d1:=D*100;
d1:=d1+0.5;
d1:=d1/100;
ShowMessage(FloatToStr(D1));
ShowMessage(FloatToStr(Trunc(1.615 * 100 + 0.5)/100));
← →
sniknik (2003-11-17 14:19) [56]Anatoly Podgoretsky © (17.11.03 14:03) [54]
как ни странно работает,
вот так не работает
var d, d1: Real48; //указать явно тип
begin
D := 1.615;
D1 := Trunc(D * 100 + 0.5)/100;
ShowMessage(FloatToStr(D1));
ShowMessage(FloatToStr(Trunc(1.615 * 100 + 0.5)/100));
...
видать тут то ему разрядности и не хватает, а тип реал зависит от директив компилятора и может быть как Real48 так и Double-ом.
> Developerr ©
кстати с Double-ом тоже есть такие числа.. :) можно нарватся.
← →
Anatoly Podgoretsky (2003-11-17 14:22) [57]sniknik © (17.11.03 14:19) [56]
1.61 и 1.62, поскольку тип был не указан, то использовался тип Double, но это не принципиально, поскольку меняется точность
← →
Developerr (2003-11-17 15:21) [58]
> Anatoly Podgoretsky ©
> Ну, ну, не поленись проверить.
>
> D := 1.615;
> D1 := Trunc(D * 100 + 0.5)/100;
> ShowMessage(FloatToStr(D1));
> ShowMessage(FloatToStr(Trunc(1.615 * 100 + 0.5)/100));
> У тебя огромная дыра в понимании чисел с плавающей запятой
Не поленился! И вчем прикол? Показывает 2 одинаковых сообщения с текстом 1.62.
В чем проблема???
← →
BlackTiger (2003-11-17 15:32) [59]Попробую вспомнить свою функцию... кажется было так:
function ValidRoundTo(D : double; UpTo : double) : double;
var
n, r : double;
begin
n := Trunc(D / UpTo); //извлекаем целую часть
r := Trunc((D - n) * 10); //получаем остаток
if r >= 5 then n := n + 1; // если остаток 5 то накручиваем еще единицу
Result := r * UpTo; //приводим число "обратно"
end;
используется так:
r := ValidRoundUp(345.3145, 0.01); //до 2х знаков {r = 345.31}
r := ValidRoundUp(345.3145, 0.001); //до 3х знаков {r = 345.315}
r := ValidRoundUp(345.3145, 100); //до сотен {r = 300}
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2003.11.27;
Скачать: [xml.tar.bz2];
Память: 0.59 MB
Время: 0.01 c