Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.11.27;
Скачать: CL | DM;

Вниз

Как округлить дробное число с 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;
Скачать: CL | DM;

Наверх




Память: 0.63 MB
Время: 0.017 c
1-89987
genek84
2003-11-17 12:58
2003.11.27
Вертикальное меню в стиле Outlook


1-89890
Oleg Khvostenko
2003-11-15 13:46
2003.11.27
Real в Integer


3-89727
npAKTuk
2003-11-07 06:27
2003.11.27
Перекрещение Join-ов


3-89791
sokohigh
2003-11-06 17:12
2003.11.27
Нужен улучшенный DBLookupComboBox...


14-90096
K.o.Z
2003-11-04 01:53
2003.11.27
HTML