{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##断言函数\n", "**单元测试通常使用断言函数作为测试的组成部分。**在进行数值计算时,我们经常遇到比较两个近似相等的浮点数这样的基本问题,由于计算机对浮点数的表示本身就不精确,所以浮点数的比较并不是那么简单。\n", "\n", "numpy.testing包中有很多实用的工具函数考虑了浮点数的比较,可以测试前提是否成立。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[NumPy的testing模块文档](http://docs.scipy.org/doc/numpy/reference/routines.testing.html)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##1. assert_almost_equal断言近似相等\n", "assert_almost_equal函数的作用是,如果两个数字的近似程度没有达到指定精度,就抛出异常。" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Decimal 6 None\n" ] } ], "source": [ "#使用assert_almost_equal函数来检查它们是否近似相等\n", "\n", "#指定精度,小数点后7位\n", "print \"Decimal 6\", np.testing.assert_almost_equal(0.123456789, 0.123456780, decimal=7)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Decimal 7" ] }, { "ename": "AssertionError", "evalue": "\nArrays are not almost equal to 8 decimals\n ACTUAL: 0.123456789\n DESIRED: 0.12345678", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m#指定精度,小数点后8位\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;31m#抛出异常\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[1;32mprint\u001b[0m \u001b[1;34m\"Decimal 7\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0massert_almost_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m0.123456789\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.123456780\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdecimal\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m8\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32md:\\Python27_32\\lib\\site-packages\\numpy\\testing\\utils.pyc\u001b[0m in \u001b[0;36massert_almost_equal\u001b[1;34m(actual, desired, decimal, err_msg, verbose)\u001b[0m\n\u001b[0;32m 488\u001b[0m \u001b[1;32mpass\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 489\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mround\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mabs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdesired\u001b[0m \u001b[1;33m-\u001b[0m \u001b[0mactual\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdecimal\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m!=\u001b[0m \u001b[1;36m0\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 490\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mAssertionError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0m_build_err_msg\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 491\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 492\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mAssertionError\u001b[0m: \nArrays are not almost equal to 8 decimals\n ACTUAL: 0.123456789\n DESIRED: 0.12345678" ] } ], "source": [ "#指定精度,小数点后8位\n", "#抛出异常\n", "print \"Decimal 7\", np.testing.assert_almost_equal(0.123456789, 0.123456780, decimal=8)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##2. assert_approx_equal断言近似相等\n", "如果两个数字的近似程度没有达到指定的有效数字要求,assert_approx_equal函数就抛出异常。\n", "\n", "触发条件为:abs(actual-expected) >= 10**(significant-1)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Significance 8 None\n" ] } ], "source": [ "# 指定8位有效数字\n", "print \"Significance 8\", np.testing.assert_approx_equal(0.123456789,0.123456780, significant=8)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Significance 9" ] }, { "ename": "AssertionError", "evalue": "\nItems are not equal to 9 significant digits:\n ACTUAL: 0.123456789\n DESIRED: 0.12345678", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m# 指定9位有效数字\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;31m# 抛出异常\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[1;32mprint\u001b[0m \u001b[1;34m\"Significance 9\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0massert_approx_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m0.123456789\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m0.123456780\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msignificant\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m9\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32md:\\Python27_32\\lib\\site-packages\\numpy\\testing\\utils.pyc\u001b[0m in \u001b[0;36massert_approx_equal\u001b[1;34m(actual, desired, significant, err_msg, verbose)\u001b[0m\n\u001b[0;32m 585\u001b[0m \u001b[1;32mpass\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 586\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mabs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msc_desired\u001b[0m \u001b[1;33m-\u001b[0m \u001b[0msc_actual\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m>=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpower\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m10.\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msignificant\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 587\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mAssertionError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 588\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 589\u001b[0m def assert_array_compare(comparison, x, y, err_msg='', verbose=True,\n", "\u001b[1;31mAssertionError\u001b[0m: \nItems are not equal to 9 significant digits:\n ACTUAL: 0.123456789\n DESIRED: 0.12345678" ] } ], "source": [ "# 指定9位有效数字\n", "# 抛出异常\n", "print \"Significance 9\", np.testing.assert_approx_equal(0.123456789,0.123456780, significant=9)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##3. assert_array_almost_equal断言数组近似相等\n", "如果两个数组中元素的近似程度没有达到指定的精度要求,assert_array_almost_equal函数将抛出异常。\n", "\n", "触发条件为: |expected - actual| < 0.5 * 10^(-decimal)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Decimal 8 None\n" ] } ], "source": [ "print \"Decimal 8\", np.testing.assert_array_almost_equal([0, 0.123456789], [0, 0.123456780], decimal=8)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Decimal 9" ] }, { "ename": "AssertionError", "evalue": "\nArrays are not almost equal to 9 decimals\n\n(mismatch 50.0%)\n x: array([ 0. , 0.123456789])\n y: array([ 0. , 0.12345678])", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mprint\u001b[0m \u001b[1;34m\"Decimal 9\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0massert_array_almost_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.123456789\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0.123456780\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdecimal\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m9\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32md:\\Python27_32\\lib\\site-packages\\numpy\\testing\\utils.pyc\u001b[0m in \u001b[0;36massert_array_almost_equal\u001b[1;34m(x, y, decimal, err_msg, verbose)\u001b[0m\n\u001b[0;32m 840\u001b[0m assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose,\n\u001b[0;32m 841\u001b[0m \u001b[0mheader\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Arrays are not almost equal to %d decimals'\u001b[0m \u001b[1;33m%\u001b[0m \u001b[0mdecimal\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 842\u001b[1;33m precision=decimal)\n\u001b[0m\u001b[0;32m 843\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 844\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32md:\\Python27_32\\lib\\site-packages\\numpy\\testing\\utils.pyc\u001b[0m in \u001b[0;36massert_array_compare\u001b[1;34m(comparison, x, y, err_msg, verbose, header, precision)\u001b[0m\n\u001b[0;32m 663\u001b[0m names=('x', 'y'), precision=precision)\n\u001b[0;32m 664\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mcond\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 665\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mAssertionError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 666\u001b[0m \u001b[1;32mexcept\u001b[0m \u001b[0mValueError\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 667\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtraceback\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mAssertionError\u001b[0m: \nArrays are not almost equal to 9 decimals\n\n(mismatch 50.0%)\n x: array([ 0. , 0.123456789])\n y: array([ 0. , 0.12345678])" ] } ], "source": [ "print \"Decimal 9\", np.testing.assert_array_almost_equal([0, 0.123456789], [0, 0.123456780], decimal=9)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##4. assert_array_equal断言数组相等\n", "如果两个数组对象不相同,assert_array_equal函数将抛出异常。两个数组相等必须形状一致且元素也严格相等,允许数组存在NaN元素。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "比较数组也可以使用assert_allclose函数。该函数有参数atol(absolute tolerance,绝对容差限)和rtol(relative tolerance,相对容差限)。对于两个数组a和b,将测试是否满足以下条件:| a - b | <= (atol+rtol*b)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Pass None\n" ] } ], "source": [ "print \"Pass\", np.testing.assert_allclose([0,0.123456789,np.nan],[0,0.123456780,np.nan], rtol=1e-7,atol=0)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fail" ] }, { "ename": "AssertionError", "evalue": "\nArrays are not equal\n\n(mismatch 50.0%)\n x: array([ 0. , 0.123457, nan])\n y: array([ 0. , 0.123457, nan])", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mprint\u001b[0m \u001b[1;34m\"Fail\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0massert_array_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m0.123456789\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnan\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m0.123456780\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnan\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32md:\\Python27_32\\lib\\site-packages\\numpy\\testing\\utils.pyc\u001b[0m in \u001b[0;36massert_array_equal\u001b[1;34m(x, y, err_msg, verbose)\u001b[0m\n\u001b[0;32m 737\u001b[0m \"\"\"\n\u001b[0;32m 738\u001b[0m assert_array_compare(operator.__eq__, x, y, err_msg=err_msg,\n\u001b[1;32m--> 739\u001b[1;33m verbose=verbose, header='Arrays are not equal')\n\u001b[0m\u001b[0;32m 740\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 741\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0massert_array_almost_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdecimal\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m6\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merr_msg\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m''\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mverbose\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;32md:\\Python27_32\\lib\\site-packages\\numpy\\testing\\utils.pyc\u001b[0m in \u001b[0;36massert_array_compare\u001b[1;34m(comparison, x, y, err_msg, verbose, header, precision)\u001b[0m\n\u001b[0;32m 663\u001b[0m names=('x', 'y'), precision=precision)\n\u001b[0;32m 664\u001b[0m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mcond\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 665\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mAssertionError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 666\u001b[0m \u001b[1;32mexcept\u001b[0m \u001b[0mValueError\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 667\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtraceback\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mAssertionError\u001b[0m: \nArrays are not equal\n\n(mismatch 50.0%)\n x: array([ 0. , 0.123457, nan])\n y: array([ 0. , 0.123457, nan])" ] } ], "source": [ "print \"Fail\", np.testing.assert_array_equal([0,0.123456789,np.nan],[0,0.123456780,np.nan])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##5. 数组排序\n", "两个数组必须形状一致并且第一个数组元素严格小于第二个数组元素,否则assert_array_less函数将抛出异常。" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Pass None\n" ] } ], "source": [ "# assert_array_less函数比较两个有严格顺序的数组\n", "print \"Pass\", np.testing.assert_array_less([0,0.1,np.nan], [1,0.2,np.nan])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##6. assert_equal比较对象\n", "这里的对象不一定是NumPy数组对象,也可以是Python中的列表、元组或字典。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##7. assert_string_equal字符串比较\n", "assert_string_equal函数断言两个字符串变量完全相同。如果测试不通过,将会抛出异常并显示两个字符串之间的差别。该函数区分大小写," ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fail" ] }, { "ename": "AssertionError", "evalue": "Differences in strings:\n- NumPy? ^\n+ Numpy? ^", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mprint\u001b[0m \u001b[1;34m\"Fail\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0massert_string_equal\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"NumPy\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"Numpy\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32md:\\Python27_32\\lib\\site-packages\\numpy\\testing\\utils.pyc\u001b[0m in \u001b[0;36massert_string_equal\u001b[1;34m(actual, desired)\u001b[0m\n\u001b[0;32m 981\u001b[0m \u001b[0mmsg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'Differences in strings:\\n%s'\u001b[0m \u001b[1;33m%\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m''\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdiff_list\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrstrip\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 982\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mactual\u001b[0m \u001b[1;33m!=\u001b[0m \u001b[0mdesired\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 983\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mAssertionError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 984\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 985\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mAssertionError\u001b[0m: Differences in strings:\n- NumPy? ^\n+ Numpy? ^" ] } ], "source": [ "print \"Fail\", np.testing.assert_string_equal(\"NumPy\", \"Numpy\")" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "##8. 浮点数比较\n", "浮点数在计算机中是以不精确的方式表示的,这给浮点数的比较带来了问题。NumPy中的assert_array_almost_equal_nulp和assert_array_max_ulp函数可以提供可靠的浮点数比较功能。ULP是Unit of Least Precision的缩写,即浮点数的最小精度单位。根据IEEE 754标准,四则运算的误差必须保持在半个ULP之内。\n", "\n", "机器精度(machine epsilon)是指浮点运算中的相对舍入误差上界。机器精度等于ULP相对于1的值。NumPy的finfo函数可以获取机器精度。" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Eps 2.22044604925e-16\n" ] } ], "source": [ "# 使用finfo函数确定机器精度\n", "eps = np.finfo(float).eps\n", "print \"Eps\", eps" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "使用assert_array_almost_equal_nulp函数比较两个近似相等的浮点数1.0和1.0+eps" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "one eps None\n" ] } ], "source": [ "print \"one eps\", np.testing.assert_array_almost_equal_nulp(1.0, 1.0+eps)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "two eps" ] }, { "ename": "AssertionError", "evalue": "X and Y are not equal to 1 ULP (max is 2)", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mAssertionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mprint\u001b[0m \u001b[1;34m\"two eps\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0massert_array_almost_equal_nulp\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1.0\u001b[0m\u001b[1;33m+\u001b[0m\u001b[0meps\u001b[0m\u001b[1;33m*\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32md:\\Python27_32\\lib\\site-packages\\numpy\\testing\\utils.pyc\u001b[0m in \u001b[0;36massert_array_almost_equal_nulp\u001b[1;34m(x, y, nulp)\u001b[0m\n\u001b[0;32m 1356\u001b[0m \u001b[0mmax_nulp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmax\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnulp_diff\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1357\u001b[0m \u001b[0mmsg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m\"X and Y are not equal to %d ULP (max is %g)\"\u001b[0m \u001b[1;33m%\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mnulp\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmax_nulp\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1358\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mAssertionError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1359\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1360\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0massert_array_max_ulp\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmaxulp\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mNone\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mAssertionError\u001b[0m: X and Y are not equal to 1 ULP (max is 2)" ] } ], "source": [ "print \"two eps\", np.testing.assert_array_almost_equal_nulp(1.0, 1.0+eps*2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**多ULP浮点数的比较**\n", "\n", "assert_array_max_ulp函数可以指定ULP的数量作为允许的误差上界。参数maxulp接受整数作为ULP数量的上限,默认值为1。" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " one eps 1.0\n" ] } ], "source": [ "print \"one eps\", np.testing.assert_array_max_ulp(1.0, 1.0+eps)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "two eps 2.0\n" ] } ], "source": [ "print \"two eps\", np.testing.assert_array_max_ulp(1.0, 1.0+eps*2,maxulp=2)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.5" } }, "nbformat": 4, "nbformat_minor": 0 }