go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/starlark/testdata/float.star (about) 1 # Tests of Starlark 'float' 2 # option:set 3 4 load("assert.star", "assert") 5 6 # TODO(adonovan): more tests: 7 # - precision 8 # - limits 9 10 # type 11 assert.eq(type(0.0), "float") 12 13 # truth 14 assert.true(123.0) 15 assert.true(-1.0) 16 assert.true(not 0.0) 17 assert.true(-1.0e-45) 18 assert.true(float("NaN")) 19 20 # not iterable 21 assert.fails(lambda: len(0.0), 'has no len') 22 assert.fails(lambda: [x for x in 0.0], 'float value is not iterable') 23 24 # literals 25 assert.eq(type(1.234), "float") 26 assert.eq(type(1e10), "float") 27 assert.eq(type(1e+10), "float") 28 assert.eq(type(1e-10), "float") 29 assert.eq(type(1.234e10), "float") 30 assert.eq(type(1.234e+10), "float") 31 assert.eq(type(1.234e-10), "float") 32 33 # int/float equality 34 assert.eq(0.0, 0) 35 assert.eq(0, 0.0) 36 assert.eq(1.0, 1) 37 assert.eq(1, 1.0) 38 assert.true(1.23e45 != 1229999999999999973814869011019624571608236031) 39 assert.true(1.23e45 == 1229999999999999973814869011019624571608236032) 40 assert.true(1.23e45 != 1229999999999999973814869011019624571608236033) 41 assert.true(1229999999999999973814869011019624571608236031 != 1.23e45) 42 assert.true(1229999999999999973814869011019624571608236032 == 1.23e45) 43 assert.true(1229999999999999973814869011019624571608236033 != 1.23e45) 44 45 # loss of precision 46 p53 = 1<<53 47 assert.eq(float(p53-1), p53-1) 48 assert.eq(float(p53+0), p53+0) 49 assert.eq(float(p53+1), p53+0) # 50 assert.eq(float(p53+2), p53+2) 51 assert.eq(float(p53+3), p53+4) # 52 assert.eq(float(p53+4), p53+4) 53 assert.eq(float(p53+5), p53+4) # 54 assert.eq(float(p53+6), p53+6) 55 assert.eq(float(p53+7), p53+8) # 56 assert.eq(float(p53+8), p53+8) 57 58 # Regression test for https://github.com/google/starlark-go/issues/375. 59 maxint64 = (1<<63)-1 60 assert.eq(int(float(maxint64)), 9223372036854775808) 61 62 assert.true(float(p53+1) != p53+1) # comparisons are exact 63 assert.eq(float(p53+1) - (p53+1), 0) # arithmetic entails rounding 64 65 assert.fails(lambda: {123.0: "f", 123: "i"}, "duplicate key: 123") 66 67 # equal int/float values have same hash 68 d = {123.0: "x"} 69 d[123] = "y" 70 assert.eq(len(d), 1) 71 assert.eq(d[123.0], "y") 72 73 # literals (mostly covered by scanner tests) 74 assert.eq(str(0.), "0.0") 75 assert.eq(str(.0), "0.0") 76 assert.true(5.0 != 4.999999999999999) 77 assert.eq(5.0, 4.9999999999999999) # both literals denote 5.0 78 assert.eq(1.23e45, 1.23 * 1000000000000000000000000000000000000000000000) 79 assert.eq(str(1.23e-45 - (1.23 / 1000000000000000000000000000000000000000000000)), "-1.5557538194652854e-61") 80 81 nan = float("NaN") 82 inf = float("+Inf") 83 neginf = float("-Inf") 84 negzero = (-1e-323 / 10) 85 86 # -- arithmetic -- 87 88 # +float, -float 89 assert.eq(+(123.0), 123.0) 90 assert.eq(-(123.0), -123.0) 91 assert.eq(-(-(123.0)), 123.0) 92 assert.eq(+(inf), inf) 93 assert.eq(-(inf), neginf) 94 assert.eq(-(neginf), inf) 95 assert.eq(str(-(nan)), "nan") 96 # + 97 assert.eq(1.2e3 + 5.6e7, 5.60012e+07) 98 assert.eq(1.2e3 + 1, 1201) 99 assert.eq(1 + 1.2e3, 1201) 100 assert.eq(str(1.2e3 + nan), "nan") 101 assert.eq(inf + 0, inf) 102 assert.eq(inf + 1, inf) 103 assert.eq(inf + inf, inf) 104 assert.eq(str(inf + neginf), "nan") 105 # - 106 assert.eq(1.2e3 - 5.6e7, -5.59988e+07) 107 assert.eq(1.2e3 - 1, 1199) 108 assert.eq(1 - 1.2e3, -1199) 109 assert.eq(str(1.2e3 - nan), "nan") 110 assert.eq(inf - 0, inf) 111 assert.eq(inf - 1, inf) 112 assert.eq(str(inf - inf), "nan") 113 assert.eq(inf - neginf, inf) 114 # * 115 assert.eq(1.5e6 * 2.2e3, 3.3e9) 116 assert.eq(1.5e6 * 123, 1.845e+08) 117 assert.eq(123 * 1.5e6, 1.845e+08) 118 assert.eq(str(1.2e3 * nan), "nan") 119 assert.eq(str(inf * 0), "nan") 120 assert.eq(inf * 1, inf) 121 assert.eq(inf * inf, inf) 122 assert.eq(inf * neginf, neginf) 123 # % 124 assert.eq(100.0 % 7.0, 2) 125 assert.eq(100.0 % -7.0, -5) # NB: different from Go / Java 126 assert.eq(-100.0 % 7.0, 5) # NB: different from Go / Java 127 assert.eq(-100.0 % -7.0, -2) 128 assert.eq(-100.0 % 7, 5) 129 assert.eq(100 % 7.0, 2) 130 assert.eq(str(1.2e3 % nan), "nan") 131 assert.eq(str(inf % 1), "nan") 132 assert.eq(str(inf % inf), "nan") 133 assert.eq(str(inf % neginf), "nan") 134 # / 135 assert.eq(str(100.0 / 7.0), "14.285714285714286") 136 assert.eq(str(100 / 7.0), "14.285714285714286") 137 assert.eq(str(100.0 / 7), "14.285714285714286") 138 assert.eq(str(100.0 / nan), "nan") 139 # // 140 assert.eq(100.0 // 7.0, 14) 141 assert.eq(100 // 7.0, 14) 142 assert.eq(100.0 // 7, 14) 143 assert.eq(100.0 // -7.0, -15) 144 assert.eq(100 // -7.0, -15) 145 assert.eq(100.0 // -7, -15) 146 assert.eq(str(1 // neginf), "-0.0") 147 assert.eq(str(100.0 // nan), "nan") 148 149 # addition 150 assert.eq(0.0 + 1.0, 1.0) 151 assert.eq(1.0 + 1.0, 2.0) 152 assert.eq(1.25 + 2.75, 4.0) 153 assert.eq(5.0 + 7.0, 12.0) 154 assert.eq(5.1 + 7, 12.1) # float + int 155 assert.eq(7 + 5.1, 12.1) # int + float 156 157 # subtraction 158 assert.eq(5.0 - 7.0, -2.0) 159 assert.eq(5.1 - 7.1, -2.0) 160 assert.eq(5.5 - 7, -1.5) 161 assert.eq(5 - 7.5, -2.5) 162 assert.eq(0.0 - 1.0, -1.0) 163 164 # multiplication 165 assert.eq(5.0 * 7.0, 35.0) 166 assert.eq(5.5 * 2.5, 13.75) 167 assert.eq(5.5 * 7, 38.5) 168 assert.eq(5 * 7.1, 35.5) 169 170 # real division (like Python 3) 171 # The / operator is available only when the 'fp' dialect option is enabled. 172 assert.eq(100.0 / 8.0, 12.5) 173 assert.eq(100.0 / -8.0, -12.5) 174 assert.eq(-100.0 / 8.0, -12.5) 175 assert.eq(-100.0 / -8.0, 12.5) 176 assert.eq(98.0 / 8.0, 12.25) 177 assert.eq(98.0 / -8.0, -12.25) 178 assert.eq(-98.0 / 8.0, -12.25) 179 assert.eq(-98.0 / -8.0, 12.25) 180 assert.eq(2.5 / 2.0, 1.25) 181 assert.eq(2.5 / 2, 1.25) 182 assert.eq(5 / 4.0, 1.25) 183 assert.eq(5 / 4, 1.25) 184 assert.fails(lambda: 1.0 / 0, "floating-point division by zero") 185 assert.fails(lambda: 1.0 / 0.0, "floating-point division by zero") 186 assert.fails(lambda: 1 / 0.0, "floating-point division by zero") 187 188 # floored division 189 assert.eq(100.0 // 8.0, 12.0) 190 assert.eq(100.0 // -8.0, -13.0) 191 assert.eq(-100.0 // 8.0, -13.0) 192 assert.eq(-100.0 // -8.0, 12.0) 193 assert.eq(98.0 // 8.0, 12.0) 194 assert.eq(98.0 // -8.0, -13.0) 195 assert.eq(-98.0 // 8.0, -13.0) 196 assert.eq(-98.0 // -8.0, 12.0) 197 assert.eq(2.5 // 2.0, 1.0) 198 assert.eq(2.5 // 2, 1.0) 199 assert.eq(5 // 4.0, 1.0) 200 assert.eq(5 // 4, 1) 201 assert.eq(type(5 // 4), "int") 202 assert.fails(lambda: 1.0 // 0, "floored division by zero") 203 assert.fails(lambda: 1.0 // 0.0, "floored division by zero") 204 assert.fails(lambda: 1 // 0.0, "floored division by zero") 205 206 # remainder 207 assert.eq(100.0 % 8.0, 4.0) 208 assert.eq(100.0 % -8.0, -4.0) 209 assert.eq(-100.0 % 8.0, 4.0) 210 assert.eq(-100.0 % -8.0, -4.0) 211 assert.eq(98.0 % 8.0, 2.0) 212 assert.eq(98.0 % -8.0, -6.0) 213 assert.eq(-98.0 % 8.0, 6.0) 214 assert.eq(-98.0 % -8.0, -2.0) 215 assert.eq(2.5 % 2.0, 0.5) 216 assert.eq(2.5 % 2, 0.5) 217 assert.eq(5 % 4.0, 1.0) 218 assert.fails(lambda: 1.0 % 0, "floating-point modulo by zero") 219 assert.fails(lambda: 1.0 % 0.0, "floating-point modulo by zero") 220 assert.fails(lambda: 1 % 0.0, "floating-point modulo by zero") 221 222 # floats cannot be used as indices, even if integral 223 assert.fails(lambda: "abc"[1.0], "want int") 224 assert.fails(lambda: ["A", "B", "C"].insert(1.0, "D"), "want int") 225 assert.fails(lambda: range(3)[1.0], "got float, want int") 226 227 # -- comparisons -- 228 # NaN 229 assert.true(nan == nan) # \ 230 assert.true(nan >= nan) # unlike Python 231 assert.true(nan <= nan) # / 232 assert.true(not (nan > nan)) 233 assert.true(not (nan < nan)) 234 assert.true(not (nan != nan)) # unlike Python 235 # Sort is stable: 0.0 and -0.0 are equal, but they are not permuted. 236 # Similarly 1 and 1.0. 237 assert.eq( 238 str(sorted([inf, neginf, nan, 1e300, -1e300, 1.0, -1.0, 1, -1, 1e-300, -1e-300, 0, 0.0, negzero, 1e-300, -1e-300])), 239 "[-inf, -1e+300, -1.0, -1, -1e-300, -1e-300, 0, 0.0, -0.0, 1e-300, 1e-300, 1.0, 1, 1e+300, +inf, nan]") 240 241 # Sort is stable, and its result contains no adjacent x, y such that y > x. 242 # Note: Python's reverse sort is unstable; see https://bugs.python.org/issue36095. 243 assert.eq(str(sorted([7, 3, nan, 1, 9])), "[1, 3, 7, 9, nan]") 244 assert.eq(str(sorted([7, 3, nan, 1, 9], reverse=True)), "[nan, 9, 7, 3, 1]") 245 246 # All NaN values compare equal. (Identical objects compare equal.) 247 nandict = {nan: 1} 248 nandict[nan] = 2 249 assert.eq(len(nandict), 1) # (same as Python) 250 assert.eq(nandict[nan], 2) # (same as Python) 251 assert.fails(lambda: {nan: 1, nan: 2}, "duplicate key: nan") 252 253 nandict[float('nan')] = 3 # a distinct NaN object 254 assert.eq(str(nandict), "{nan: 3}") # (Python: {nan: 2, nan: 3}) 255 256 assert.eq(str({inf: 1, neginf: 2}), "{+inf: 1, -inf: 2}") 257 258 # zero 259 assert.eq(0.0, negzero) 260 261 # inf 262 assert.eq(+inf / +inf, nan) 263 assert.eq(+inf / -inf, nan) 264 assert.eq(-inf / +inf, nan) 265 assert.eq(0.0 / +inf, 0.0) 266 assert.eq(0.0 / -inf, 0.0) 267 assert.true(inf > -inf) 268 assert.eq(inf, -neginf) 269 # TODO(adonovan): assert inf > any finite number, etc. 270 271 # negative zero 272 negz = -0 273 assert.eq(negz, 0) 274 275 # min/max ordering with NaN (the greatest float value) 276 assert.eq(max([1, nan, 3]), nan) 277 assert.eq(max([nan, 2, 3]), nan) 278 assert.eq(min([1, nan, 3]), 1) 279 assert.eq(min([nan, 2, 3]), 2) 280 281 # float/float comparisons 282 fltmax = 1.7976931348623157e+308 # approx 283 fltmin = 4.9406564584124654e-324 # approx 284 assert.lt(-inf, -fltmax) 285 assert.lt(-fltmax, -1.0) 286 assert.lt(-1.0, -fltmin) 287 assert.lt(-fltmin, 0.0) 288 assert.lt(0, fltmin) 289 assert.lt(fltmin, 1.0) 290 assert.lt(1.0, fltmax) 291 assert.lt(fltmax, inf) 292 293 # int/float comparisons 294 assert.eq(0, 0.0) 295 assert.eq(1, 1.0) 296 assert.eq(-1, -1.0) 297 assert.ne(-1, -1.0 + 1e-7) 298 assert.lt(-2, -2 + 1e-15) 299 300 # int conversion (rounds towards zero) 301 assert.eq(int(100.1), 100) 302 assert.eq(int(100.0), 100) 303 assert.eq(int(99.9), 99) 304 assert.eq(int(-99.9), -99) 305 assert.eq(int(-100.0), -100) 306 assert.eq(int(-100.1), -100) 307 assert.eq(int(1e100), int("10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104")) 308 assert.fails(lambda: int(inf), "cannot convert.*infinity") 309 assert.fails(lambda: int(nan), "cannot convert.*NaN") 310 311 # -- float() function -- 312 assert.eq(float(), 0.0) 313 # float(bool) 314 assert.eq(float(False), 0.0) 315 assert.eq(float(True), 1.0) 316 # float(int) 317 assert.eq(float(0), 0.0) 318 assert.eq(float(1), 1.0) 319 assert.eq(float(123), 123.0) 320 assert.eq(float(123 * 1000000 * 1000000 * 1000000 * 1000000 * 1000000), 1.23e+32) 321 # float(float) 322 assert.eq(float(1.1), 1.1) 323 assert.fails(lambda: float(None), "want number or string") 324 assert.ne(False, 0.0) # differs from Python 325 assert.ne(True, 1.0) 326 # float(string) 327 assert.eq(float("1.1"), 1.1) 328 assert.fails(lambda: float("1.1abc"), "invalid float literal") 329 assert.fails(lambda: float("1e100.0"), "invalid float literal") 330 assert.fails(lambda: float("1e1000"), "floating-point number too large") 331 assert.eq(float("-1.1"), -1.1) 332 assert.eq(float("+1.1"), +1.1) 333 assert.eq(float("+Inf"), inf) 334 assert.eq(float("-Inf"), neginf) 335 assert.eq(float("NaN"), nan) 336 assert.eq(float("NaN"), nan) 337 assert.eq(float("+NAN"), nan) 338 assert.eq(float("-nan"), nan) 339 assert.eq(str(float("Inf")), "+inf") 340 assert.eq(str(float("+INF")), "+inf") 341 assert.eq(str(float("-inf")), "-inf") 342 assert.eq(str(float("+InFiniTy")), "+inf") 343 assert.eq(str(float("-iNFiniTy")), "-inf") 344 assert.fails(lambda: float("one point two"), "invalid float literal: one point two") 345 assert.fails(lambda: float("1.2.3"), "invalid float literal: 1.2.3") 346 assert.fails(lambda: float(123 << 500 << 500 << 50), "int too large to convert to float") 347 assert.fails(lambda: float(-123 << 500 << 500 << 50), "int too large to convert to float") 348 assert.fails(lambda: float(str(-123 << 500 << 500 << 50)), "floating-point number too large") 349 350 # -- implicit float(int) conversions -- 351 assert.fails(lambda: (1<<500<<500<<500) + 0.0, "int too large to convert to float") 352 assert.fails(lambda: 0.0 + (1<<500<<500<<500), "int too large to convert to float") 353 assert.fails(lambda: (1<<500<<500<<500) - 0.0, "int too large to convert to float") 354 assert.fails(lambda: 0.0 - (1<<500<<500<<500), "int too large to convert to float") 355 assert.fails(lambda: (1<<500<<500<<500) * 1.0, "int too large to convert to float") 356 assert.fails(lambda: 1.0 * (1<<500<<500<<500), "int too large to convert to float") 357 assert.fails(lambda: (1<<500<<500<<500) / 1.0, "int too large to convert to float") 358 assert.fails(lambda: 1.0 / (1<<500<<500<<500), "int too large to convert to float") 359 assert.fails(lambda: (1<<500<<500<<500) // 1.0, "int too large to convert to float") 360 assert.fails(lambda: 1.0 // (1<<500<<500<<500), "int too large to convert to float") 361 assert.fails(lambda: (1<<500<<500<<500) % 1.0, "int too large to convert to float") 362 assert.fails(lambda: 1.0 % (1<<500<<500<<500), "int too large to convert to float") 363 364 365 # -- int function -- 366 assert.eq(int(0.0), 0) 367 assert.eq(int(1.0), 1) 368 assert.eq(int(1.1), 1) 369 assert.eq(int(0.9), 0) 370 assert.eq(int(-1.1), -1.0) 371 assert.eq(int(-1.0), -1.0) 372 assert.eq(int(-0.9), 0.0) 373 assert.eq(int(1.23e+32), 123000000000000004979083645550592) 374 assert.eq(int(-1.23e-32), 0) 375 assert.eq(int(1.23e-32), 0) 376 assert.fails(lambda: int(float("+Inf")), "cannot convert float infinity to integer") 377 assert.fails(lambda: int(float("-Inf")), "cannot convert float infinity to integer") 378 assert.fails(lambda: int(float("NaN")), "cannot convert float NaN to integer") 379 380 381 # hash 382 # Check that equal float and int values have the same internal hash. 383 def checkhash(): 384 for a in [1.23e100, 1.23e10, 1.23e1, 1.23, 385 1, 4294967295, 8589934591, 9223372036854775807]: 386 for b in [a, -a, 1/a, -1/a]: 387 f = float(b) 388 i = int(b) 389 if f == i: 390 fh = {f: None} 391 ih = {i: None} 392 if fh != ih: 393 assert.true(False, "{%v: None} != {%v: None}: hashes vary" % fh, ih) 394 checkhash() 395 396 # string formatting 397 398 # %d 399 assert.eq("%d" % 0, "0") 400 assert.eq("%d" % 0.0, "0") 401 assert.eq("%d" % 123, "123") 402 assert.eq("%d" % 123.0, "123") 403 assert.eq("%d" % 1.23e45, "1229999999999999973814869011019624571608236032") 404 # (see below for '%d' % NaN/Inf) 405 assert.eq("%d" % negzero, "0") 406 assert.fails(lambda: "%d" % float("NaN"), "cannot convert float NaN to integer") 407 assert.fails(lambda: "%d" % float("+Inf"), "cannot convert float infinity to integer") 408 assert.fails(lambda: "%d" % float("-Inf"), "cannot convert float infinity to integer") 409 410 # %e 411 assert.eq("%e" % 0, "0.000000e+00") 412 assert.eq("%e" % 0.0, "0.000000e+00") 413 assert.eq("%e" % 123, "1.230000e+02") 414 assert.eq("%e" % 123.0, "1.230000e+02") 415 assert.eq("%e" % 1.23e45, "1.230000e+45") 416 assert.eq("%e" % -1.23e-45, "-1.230000e-45") 417 assert.eq("%e" % nan, "nan") 418 assert.eq("%e" % inf, "+inf") 419 assert.eq("%e" % neginf, "-inf") 420 assert.eq("%e" % negzero, "-0.000000e+00") 421 assert.fails(lambda: "%e" % "123", "requires float, not str") 422 # %f 423 assert.eq("%f" % 0, "0.000000") 424 assert.eq("%f" % 0.0, "0.000000") 425 assert.eq("%f" % 123, "123.000000") 426 assert.eq("%f" % 123.0, "123.000000") 427 # Note: Starlark/Java emits 1230000000000000000000000000000000000000000000.000000. Why? 428 assert.eq("%f" % 1.23e45, "1229999999999999973814869011019624571608236032.000000") 429 assert.eq("%f" % -1.23e-45, "-0.000000") 430 assert.eq("%f" % nan, "nan") 431 assert.eq("%f" % inf, "+inf") 432 assert.eq("%f" % neginf, "-inf") 433 assert.eq("%f" % negzero, "-0.000000") 434 assert.fails(lambda: "%f" % "123", "requires float, not str") 435 # %g 436 assert.eq("%g" % 0, "0.0") 437 assert.eq("%g" % 0.0, "0.0") 438 assert.eq("%g" % 123, "123.0") 439 assert.eq("%g" % 123.0, "123.0") 440 assert.eq("%g" % 1.110, "1.11") 441 assert.eq("%g" % 1e5, "100000.0") 442 assert.eq("%g" % 1e6, "1e+06") # Note: threshold of scientific notation is 1e17 in Starlark/Java 443 assert.eq("%g" % 1.23e45, "1.23e+45") 444 assert.eq("%g" % -1.23e-45, "-1.23e-45") 445 assert.eq("%g" % nan, "nan") 446 assert.eq("%g" % inf, "+inf") 447 assert.eq("%g" % neginf, "-inf") 448 assert.eq("%g" % negzero, "-0.0") 449 # str uses %g 450 assert.eq(str(0.0), "0.0") 451 assert.eq(str(123.0), "123.0") 452 assert.eq(str(1.23e45), "1.23e+45") 453 assert.eq(str(-1.23e-45), "-1.23e-45") 454 assert.eq(str(nan), "nan") 455 assert.eq(str(inf), "+inf") 456 assert.eq(str(neginf), "-inf") 457 assert.eq(str(negzero), "-0.0") 458 assert.fails(lambda: "%g" % "123", "requires float, not str") 459 460 i0 = 1 461 f0 = 1.0 462 assert.eq(type(i0), "int") 463 assert.eq(type(f0), "float") 464 465 ops = { 466 '+': lambda x, y: x + y, 467 '-': lambda x, y: x - y, 468 '*': lambda x, y: x * y, 469 '/': lambda x, y: x / y, 470 '//': lambda x, y: x // y, 471 '%': lambda x, y: x % y, 472 } 473 474 # Check that if either argument is a float, so too is the result. 475 def checktypes(): 476 want = set(""" 477 int + int = int 478 int + float = float 479 float + int = float 480 float + float = float 481 int - int = int 482 int - float = float 483 float - int = float 484 float - float = float 485 int * int = int 486 int * float = float 487 float * int = float 488 float * float = float 489 int / int = float 490 int / float = float 491 float / int = float 492 float / float = float 493 int // int = int 494 int // float = float 495 float // int = float 496 float // float = float 497 int % int = int 498 int % float = float 499 float % int = float 500 float % float = float 501 """[1:].splitlines()) 502 for opname in ("+", "-", "*", "/", "%"): 503 for x in [i0, f0]: 504 for y in [i0, f0]: 505 op = ops[opname] 506 got = "%s %s %s = %s" % (type(x), opname, type(y), type(op(x, y))) 507 assert.contains(want, got) 508 checktypes()