验证数字精度/比例
Posted
技术标签:
【中文标题】验证数字精度/比例【英文标题】:Validating number precision/scale 【发布时间】:2011-09-10 01:41:02 【问题描述】:如何验证从表单发布的数字的精度/比例,以确保它可以存储在 Oracle NUMBER 列中?例如:
<input type="number" name="foo" value="123.45" />
用户将表单提交到 php 后端...
<?php
function isValidNumber($number, $precision, $scale)
// ???
return $isValid;
// The precision and scale here are actually dynamic
$isValid = isValidNumber($_POST['foo'], 5, 2);
...我希望能够验证数字而不尝试在 Oracle 中插入/更新它并处理任何精度溢出错误(主动设计,而不是被动设计)。我还没有想出一种准确验证所有各种边缘情况的方法(Oracle 不会产生比例溢出错误 - 它只是四舍五入到最大值,但这种四舍五入可能导致精度溢出,这确实会产生错误等)。
【问题讨论】:
您使用什么库来连接您的 Oracle 数据库? 【参考方案1】:function isValidNumber($number, $precision, $scale)
$isValid = false;
if (is_numeric($number))
$num = round(abs($number), $scale);
$max = str_repeat('9',$precision - $scale).'.'.str_repeat('9',$scale);
$isValid = $num <= $max;
return $isValid;
isValidNumber($number, 5, 2)
的输出
123.456 (valid)
9999.999 (invalid)
99999.999 (invalid)
12.003 (valid)
999.99 (valid)
999.999 (invalid)
1234.5 (invalid)
最后
isValid(1234567890123456789012345678.90, 30, 2) == **valid**
【讨论】:
感谢您的回答,但是对于有效的 Oracle 输入,此功能失败。例如,“123.456”是 NUMBER(5, 2) 列的有效输入。 Oracle 将简单地将其四舍五入并将其存储为“123.46”。 你不是说要阻止 Oracle 舍入它吗? 不,我只是想确保我给 Oracle 的任何数字都不会产生溢出错误。这个函数可以做到这一点,但它也会阻止 Oracle 不会产生错误的值。 好的,我更改了上面代码中的第 4 行。看看是否有帮助。 :) 这更好,但在比例舍入产生精度错误的情况下仍然失败。例如,isValidNumber("999.999", 5, 2) 应该返回 false,但您的版本返回 true。它应该返回 false,因为 Oracle 将 999.999 舍入到 1000.00,因为比例为 2。1000.00 的精度为 6,因此会产生溢出错误。【参考方案2】:您可以使用 n 种方法来实现这一点。以下可以作为起点
使用 html5 验证的客户端验证建议的方法是仅使用 HTML5 使用基于正则表达式模式的匹配。
input type="text" pattern="regex"
免责声明:模式逻辑尚未经过测试,因此您必须在任何地方使用之前对其进行测试
-?([0-9]0,precision-scale\.[0-9]1,scale|[0-9]1,precision-scale)
相同的正则表达式逻辑也可以用于以下任何有自己的加号和减号的层
使用 Java 脚本验证的客户端 使用 php 验证的服务器端 在 DB 层进行验证并在不同的地方抛出错误 层【讨论】:
感谢您的回答,但它没有解决比例舍入问题。 对不起,无法得到这个...如果数字不在配置的比例值中,并且您想在 UI 层中处理这个问题,Oracle 会四舍五入。 Regex 模式将匹配,您可以对不匹配的模式发出验证警告。我在这里错过了什么吗? 您给出的正则表达式匹配“999999999999.999999999999”和其他可能导致数据库错误的无效数据。 谢谢,但新的正则表达式仍然匹配“999999999999.999999999999”等无效数据。 客户端验证不可靠。始终在服务器端进行验证。【参考方案3】:获取字符串的长度,获取小数的位置 这将为您提供总小数位数
$len = strlen($num);
$p = strpos($num, '.');
$dec_plcs = ($len - $p) - 1;
【讨论】:
感谢您的反馈,但这并不能验证精度或规模。超过以上是关于验证数字精度/比例的主要内容,如果未能解决你的问题,请参考以下文章