如何解决176.04变为176.039999的问题

dingjd 2000-12-09 04:03:00
某字段需要6位小数,我现在SQL Server中创建表,并设置该字段的数据类型为numeric(19,6),在程序中我采用TQuery和TDBGrid相连,并允许TQuery编辑。但我在TQuery中直接输入某些数值时,该数值却不够精确,例如当输入176.04时,却自动变为176.039999,通过SQL Server的Query Analyzer查看,存储的数值亦为176.039999。我试图通过BDE的BCE=True来实现,但BCD最大支持4位小数,不能满足需要,我试用ADO后仍然无效,改为ODBC后数值却可以正常输入和存储,但ODBC的连接速度却比BDE要慢得多,我该如何解决176.04变为176.039999的问题,而又不影响系统的性能?请各位高手指点,谢谢。
...全文
482 31 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
nononono 2000-12-19
  • 打赏
  • 举报
回复
to GoodHope:
你说的原理大家应该都知道。但开发工具实际上对此一般都有特别处理。很多工具就是按指定的小数位数进行相对精确的计算(比如:VFP)。我们现在要解决的是:Delphi/CB是否提供了这样的方法。EanbleBCD本来就是为这个问题而设的(但好象不支持6位小数)

to BCB:
我用BDE时,77.77就是变成了 77.769999,我们的CB版本是不是有区别?怪事。

解决的方法还是有的,但各位还有什么方法在前端输入时直接解决?最好不要在后台处理了。
supershan 2000-12-15
  • 打赏
  • 举报
回复
这个问题我都问过了,想处理它很简单,根据具体情况分析,看你要达到什么效果了。
function FloatToStrF(Value: Extended; Format: TFloatFormat; Precision, Digits: Integer): string;
用这个什么都可以解决.但麻烦在如里你小数位不固定
GoodHope 2000-12-13
  • 打赏
  • 举报
回复
再强调一次,浮点运算是很麻烦的东西,很容易出错。处理它没有什么简单的办法,只有非常的小心,仔细的检查。如果不是必要,尽量用整数或者定点数来取代浮点数。
GoodHope 2000-12-13
  • 打赏
  • 举报
回复
在学习程序设计的时候,在浮点运算部分相信都学过,如果要判断两个浮点数是否相等不应该直接像(DoubleA = DoubleB)比较,而应该检查二者的差是否小于一个足够小的浮点数,像(ABS(DoubleA-DoubleB) < aVerySmallDouble)。就是因为浮点有舍入误差,而且是无法避免的。

to:nononono
硬件已经决定了不可能在输入时解决,现在通用的办法就是在计算过程中使用更高级的精度。比如你需要10位有效数字,就可以采用Double型,它提供了15位精度,因此就是有一点舍入误差,也发生在15位,前10位的精度还是正确的。如果中间过程较多,有两个办法,一,采用Extended型,它提供了19位精度;二,在中途进行校准,修正舍入造成的误差。
to:dingjd
数值计算都是这样处理浮点的舍入误差,这就是可行的解决方法。不要指望所有问题都能轻易解决。
to:BCB
你没有碰到把176.04变成176.0399……,是因为SQL在某些显示处理中是对小数点后两位进行了舍入。所以77.770004变成了77.77。SQL和ADO我都不熟,所以不知道怎么设置什么时候会在多少位舍入。
BCB 2000-12-13
  • 打赏
  • 举报
回复
好象BDE 的TQuery不出现精度问题,
用的ADO会出现问题,如在DBGrid中录入77.770009
实际变成了 77.77, 这超过了精度允许的范围,就
是四舍五入,也不允许相差这么多,ADO有BUG!!!!
GoodHope 2000-12-12
  • 打赏
  • 举报
回复
这是浮点数二进制表示问题带来的,与工具无关。浮点数只有由1/(2^n)组成的小数才没有误差。 其中Double型的n=52,Extended型的n=64,Single型的n=23。Real48是Borland定义的,估计n=38。这种问题在浮点运算中是常见问题。解决的办法就是,在计算过程中使用更高级的进度,在输出是进行舍入。当然也可以使用BCD码来解决,但是执行效率太低。
BCB 2000-12-12
  • 打赏
  • 举报
回复
ADODataset1 将77.770004变成 77.77, SQL Server7 中也77.77
TQuery 77.770004不变,但在ADODataset1仍显成77.77,
我也疯了,不过我的ADO未带升级包, 可我喜欢ADO,咱办?!




BCB 2000-12-12
  • 打赏
  • 举报
回复
怪,我的176.04从未变成176.039999

问题可能出在ADO上,
与DBGrid、SQL SERVER无关,
BCB 2000-12-12
  • 打赏
  • 举报
回复
若DBGrid1的间接源是ADODataset1,会出现 77.770001变成77.77,
SQL Server 7 也是77.77;

若DBGrid1的间接源是Query1,77.770001仍是77.770001,在SQL SERVER
也是77.770001

其它现象未发现

dingjd 2000-12-12
  • 打赏
  • 举报
回复
仍然没有人能够提供可行的解决方法。
nononono 2000-12-12
  • 打赏
  • 举报
回复
不会吧?

MS SQL Server & CB5

用 TQuery & TDataSource & TDBGrid。不要别的任何设置。

对表中类型为 numeric(19,6) 的字段进行输入时,如果输入:77.77,88.88等数据,经常出现少 0.000001的现象。存到表中中的也是。如果表中的数据已经是77.77, 在前端显示正确,但前端就是不能正确输入77.77。

我用TField的 DISPLAYFORMAT 和 EDITFORMAT 使显示正确了。
BCB 2000-12-12
  • 打赏
  • 举报
回复
版本差不多,奇怪了,
我未遇到过;
nononono 2000-12-12
  • 打赏
  • 举报
回复
把EanbleBCD设为true,怎么就不支持6位小数?!!我没有试。
nononono 2000-12-12
  • 打赏
  • 举报
回复
这的确是个问题,好好研究一下。
dingjd 2000-12-12
  • 打赏
  • 举报
回复
BCB,我利用Sql server的profiler跟踪了语句,发现实际执行的语句中的数值已经变为176.039999了,说明是Delphi出的问题。我的Delphi是5.0,并安装了pack1。BDE为5.11。
nononono 2000-12-12
  • 打赏
  • 举报
回复
可我想知道现在这个问题的正确答案。GoodHope 所说的对,但应该在输入时解决问题,要等输出时再解决,误差的累计会导致输出的结果错误。
nononono 2000-12-12
  • 打赏
  • 举报
回复
可我想知道现在这个问题的正确答案。GoodHope 所说的对,但应该在输入时解决问题,要等输出时再解决,误差的累计会导致输出的结果错误。
nononono 2000-12-12
  • 打赏
  • 举报
回复
BCB, 你是不是安装了 BDE 的升级包?

其实应该用 ADO. 对 MS SQL Server 7 的访问,Inprise 承认 BDE 有问题,推荐用 ADO.
BCB 2000-12-11
  • 打赏
  • 举报
回复
我严格按照你的步骤,在DBGrid1的字段中
输入176.04,显示仍是176.04,
在SQL Server的Query Analyzer中
显示的是176.040000,
毫无问题,再次说明。

BCB 2000-12-11
  • 打赏
  • 举报
回复
我按照你的步骤:
用SQL server7.0和C++BUILDER 5.0(带升级包),
ADO和BDE的Query1
都试了176.04,从未变成176.039999,
在sql server也输了几遍也没作怪,
C++BUILDER与 DELPHI高度兼容,
我想可能是你DELPHI版本有BUG?! 几点几版?


加载更多回复(11)

5,927

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧