@@ -1166,10 +1166,131 @@ def test_mtestfile(self):
11661166 '\n ' .join (failures ))
11671167
11681168
1169+ class IsCloseTests (unittest .TestCase ):
1170+ isclose = math .isclose # sublcasses should override this
1171+
1172+ def assertIsClose (self , a , b , * args , ** kwargs ):
1173+ self .assertTrue (self .isclose (a , b , * args , ** kwargs ),
1174+ msg = "%s and %s should be close!" % (a , b ))
1175+
1176+ def assertIsNotClose (self , a , b , * args , ** kwargs ):
1177+ self .assertFalse (self .isclose (a , b , * args , ** kwargs ),
1178+ msg = "%s and %s should not be close!" % (a , b ))
1179+
1180+ def assertAllClose (self , examples , * args , ** kwargs ):
1181+ for a , b in examples :
1182+ self .assertIsClose (a , b , * args , ** kwargs )
1183+
1184+ def assertAllNotClose (self , examples , * args , ** kwargs ):
1185+ for a , b in examples :
1186+ self .assertIsNotClose (a , b , * args , ** kwargs )
1187+
1188+ def test_negative_tolerances (self ):
1189+ # ValueError should be raised if either tolerance is less than zero
1190+ with self .assertRaises (ValueError ):
1191+ self .assertIsClose (1 , 1 , rel_tol = - 1e-100 )
1192+ with self .assertRaises (ValueError ):
1193+ self .assertIsClose (1 , 1 , rel_tol = 1e-100 , abs_tol = - 1e10 )
1194+
1195+ def test_identical (self ):
1196+ # identical values must test as close
1197+ identical_examples = [(2.0 , 2.0 ),
1198+ (0.1e200 , 0.1e200 ),
1199+ (1.123e-300 , 1.123e-300 ),
1200+ (12345 , 12345.0 ),
1201+ (0.0 , - 0.0 ),
1202+ (345678 , 345678 )]
1203+ self .assertAllClose (identical_examples , rel_tol = 0.0 , abs_tol = 0.0 )
1204+
1205+ def test_eight_decimal_places (self ):
1206+ # examples that are close to 1e-8, but not 1e-9
1207+ eight_decimal_places_examples = [(1e8 , 1e8 + 1 ),
1208+ (- 1e-8 , - 1.000000009e-8 ),
1209+ (1.12345678 , 1.12345679 )]
1210+ self .assertAllClose (eight_decimal_places_examples , rel_tol = 1e-8 )
1211+ self .assertAllNotClose (eight_decimal_places_examples , rel_tol = 1e-9 )
1212+
1213+ def test_near_zero (self ):
1214+ # values close to zero
1215+ near_zero_examples = [(1e-9 , 0.0 ),
1216+ (- 1e-9 , 0.0 ),
1217+ (- 1e-150 , 0.0 )]
1218+ # these should not be close to any rel_tol
1219+ self .assertAllNotClose (near_zero_examples , rel_tol = 0.9 )
1220+ # these should be close to abs_tol=1e-8
1221+ self .assertAllClose (near_zero_examples , abs_tol = 1e-8 )
1222+
1223+ def test_identical_infinite (self ):
1224+ # these are close regardless of tolerance -- i.e. they are equal
1225+ self .assertIsClose (INF , INF )
1226+ self .assertIsClose (INF , INF , abs_tol = 0.0 )
1227+ self .assertIsClose (NINF , NINF )
1228+ self .assertIsClose (NINF , NINF , abs_tol = 0.0 )
1229+
1230+ def test_inf_ninf_nan (self ):
1231+ # these should never be close (following IEEE 754 rules for equality)
1232+ not_close_examples = [(NAN , NAN ),
1233+ (NAN , 1e-100 ),
1234+ (1e-100 , NAN ),
1235+ (INF , NAN ),
1236+ (NAN , INF ),
1237+ (INF , NINF ),
1238+ (INF , 1.0 ),
1239+ (1.0 , INF ),
1240+ (INF , 1e308 ),
1241+ (1e308 , INF )]
1242+ # use largest reasonable tolerance
1243+ self .assertAllNotClose (not_close_examples , abs_tol = 0.999999999999999 )
1244+
1245+ def test_zero_tolerance (self ):
1246+ # test with zero tolerance
1247+ zero_tolerance_close_examples = [(1.0 , 1.0 ),
1248+ (- 3.4 , - 3.4 ),
1249+ (- 1e-300 , - 1e-300 )]
1250+ self .assertAllClose (zero_tolerance_close_examples , rel_tol = 0.0 )
1251+
1252+ zero_tolerance_not_close_examples = [(1.0 , 1.000000000000001 ),
1253+ (0.99999999999999 , 1.0 ),
1254+ (1.0e200 , .999999999999999e200 )]
1255+ self .assertAllNotClose (zero_tolerance_not_close_examples , rel_tol = 0.0 )
1256+
1257+ def test_assymetry (self ):
1258+ # test the assymetry example from PEP 485
1259+ self .assertAllClose ([(9 , 10 ), (10 , 9 )], rel_tol = 0.1 )
1260+
1261+ def test_integers (self ):
1262+ # test with integer values
1263+ integer_examples = [(100000001 , 100000000 ),
1264+ (123456789 , 123456788 )]
1265+
1266+ self .assertAllClose (integer_examples , rel_tol = 1e-8 )
1267+ self .assertAllNotClose (integer_examples , rel_tol = 1e-9 )
1268+
1269+ def test_decimals (self ):
1270+ # test with Decimal values
1271+ from decimal import Decimal
1272+
1273+ decimal_examples = [(Decimal ('1.00000001' ), Decimal ('1.0' )),
1274+ (Decimal ('1.00000001e-20' ), Decimal ('1.0e-20' )),
1275+ (Decimal ('1.00000001e-100' ), Decimal ('1.0e-100' ))]
1276+ self .assertAllClose (decimal_examples , rel_tol = 1e-8 )
1277+ self .assertAllNotClose (decimal_examples , rel_tol = 1e-9 )
1278+
1279+ def test_fractions (self ):
1280+ # test with Fraction values
1281+ from fractions import Fraction
1282+
1283+ # could use some more examples here!
1284+ fraction_examples = [(Fraction (1 , 100000000 ) + 1 , Fraction (1 ))]
1285+ self .assertAllClose (fraction_examples , rel_tol = 1e-8 )
1286+ self .assertAllNotClose (fraction_examples , rel_tol = 1e-9 )
1287+
1288+
11691289def test_main ():
11701290 from doctest import DocFileSuite
11711291 suite = unittest .TestSuite ()
11721292 suite .addTest (unittest .makeSuite (MathTests ))
1293+ suite .addTest (unittest .makeSuite (IsCloseTests ))
11731294 suite .addTest (DocFileSuite ("ieee754.txt" ))
11741295 run_unittest (suite )
11751296
0 commit comments