问题是这样的,我通过计算得出的数值有3位小数,现在的情况是:如果该数值小于200,那么保留一位小数,取舍原则就是4舍6入5考虑,也就是说如果小数点的第二位是大于等于6的话就直接进位,如果是等于5,那么要看第三位小数,如果第三位小数是奇数就进上,如果是偶数就舍去,经过这样处理后的第二位小数如果是6的时候就进到第一位小数,如果还是5那就舍去,然后再取整,如果该数值大于200并小于等于1000时,该数值只保留到5的倍数,如果大于1000,就保留到10的倍数,我举例如下:
198.505修约后为198
198.515修约后为199
202修约后为200
206修约后为205
1025修约后为1020
1026修约后为1030
这样程序怎样实现?谢谢!
198.505修约后为198
198.515修约后为199
202修约后为200
206修约后为205
1025修约后为1020
1026修约后为1030
这样程序怎样实现?谢谢!
trunc 和 round 是 system unit 里的函数,缺省就可以用。
floor 直接往小的取,比如 floor(-123.55)=-124,floor(123.55)=123
trunc 直接切下整数,比如 trunc(-123.55)=-123, floor(123.55)=123
ceil 直接往大的取,比如 ceil(-123.55)=-123, ceil(123.55)=124
round 计算四舍五入,比如 round(-123.55)=-124,round(123.55)=124小于200, 就只要用函数就可以了
大于200并小于等于1000时, integer MOD 10 得到尾数,然后根据你的原则处理
if 尾数 〉5 then integer := (integer DIV 10)*10 + 5 else
if 尾数 < = 5 then integer := integer - 尾数 ;
如果大于1000, integer := (integer DIV 10)*10 具体情况你自己处理
>> 哈哈,我估计大家看了就会晕,我第一次看到时也晕了,但现实的情况就是要求这样,>>算法是很明确了,但关键是小数的怎样取,怎样直接就取到第三位小数或第二位小数?我的>>意思是不用乘以100或1000这样来取把数字当作字符传处理
pos 取到小数点,然后根据你的算法判断
处理的时候当字符穿,
处理完直接strtoint就ok了,
最后也是别人帮我解决的,函数如下
const
CC_SIGNIFICANT_DIGIT = 15; //Double类型的有效位数为15(包括小数)type
TReserveDigitRang = 1..CC_SIGNIFICANT_DIGIT;{ /**************************************************
* 说明: *
* 功能同Math单元的RoundTo函数 *
* 参数: *
* 同Math单元的RoundTo函数 *
* 返回: *
* 同Math单元的RoundTo函数 *
* 备注: *
* 原Math单元中的RoundTo函数精度导致问题 *
* 比如,AValue = 0.0255, ADigit = -3 *
* 则 AValue / 0.001 实际等于25.49999999... *
* 这样Round后就等于25而不是26了 *
*************************************************/ }
function RoundToEx(const AValue: Double; const ADigit: TRoundToRange): Double;
var
LFactor: Double;
begin
LFactor := IntPower(10, ADigit); //现有的算法
//RoundToEx(0.0255, -3) = 0.026
Result := AValue / LFactor;
Result := Trunc(Result * 1000000 + 0.5) / 100; //因为最多只会取到判断位后的两位
Result := Round(Result) * LFactor; //原有的算法
//RoundToEx(0.0255, -3) = 0.025
//Result := Round(AValue / LFactor) * LFactor;
end;{ /******************************************************
* 说明: *
* 获取指定值在保留指定有效数字后的值(四舍六入) *
* 参数: *
* [ in]AValue 参与的指定值 *
* [ in]ADigit 所保留有效数字的个数 *
* 返回: *
* 期望值 *
*****************************************************/ }
function GetReserveValue(
const AValue: Double; const ADigit: TReserveDigitRang): Double;
var
iIntPart: Integer;
iIntLen: Integer;
begin
iIntLen := 0;
iIntPart := Trunc(Abs(AValue));
if iIntPart > 0 then
iIntLen := Length(IntToStr(iIntPart)); Result := RoundToEx(AValue, iIntLen - ADigit);
end;如果该数值大于200并小于等于1000时,该数值只保留到5的倍数,至于这个,你再修改一下好了,不是很难,上面的函数能解决其它问题。我用了
Result := Trunc(Result * 1000000 + 0.5) / 100; //因为最多只会取到判断位后的两位
应该改为
Result := Trunc(Result * 100 + 0.5) / 100; //因为最多只会取到判断位后的两位
其实你的这个不是很标准的银行家算法,
如果是标准的,它不只是判断5后面的那位是不是0,只要后面有不是0的数字,都应该进1,
上面的是按照你的标准做的,至于其它你可以控制上面函数的100,根据你判断的准确率来控制,我以前是控制到小数点后面第九位。
你自己先修改修改
const
CC_SIGNIFICANT_DIGIT = 15; //Double类型的有效位数为15(包括小数)type
TReserveDigitRang = 1..CC_SIGNIFICANT_DIGIT;
function RoundToEx(const AValue: Double; const ADigit: TRoundToRange): Double;
var
LFactor: Double;
begin
LFactor := IntPower(10, ADigit);
Result := AValue / LFactor;
Result := Trunc(Result * 100 + 0.5) / 100; //因为最多只会取到判断位后的两位
Result := Round(Result) * LFactor;
end;function GetReserveValue(
const AValue: Double; const ADigit: TReserveDigitRang): Double;
var
iIntPart: Integer;
iIntLen: Integer;
begin
iIntLen := 0;
iIntPart := Trunc(Abs(AValue));
if iIntPart > 0 then
iIntLen := Length(IntToStr(iIntPart)); Result := RoundToEx(AValue, iIntLen - ADigit);
end;