Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
3-89718
Zai
2003-11-10 10:26
2003.11.27
ClientDataSet в FIBPlus


1-89848
Buffoon
2003-11-16 17:49
2003.11.27
Заголовок окна


1-89990
Dmitriy M. Volkov
2003-11-17 14:15
2003.11.27
FindNext - поиск заново


4-90179
ARTEMKA
2003-10-06 02:55
2003.11.27
Регион в движении


6-90026
Tol-123
2003-10-01 14:07
2003.11.27
Широковещательный TCP пакет





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский