def _sample_conversion_decimal(dimension, is_extrapolation): """Samples to and from units and values.""" base_unit, target_unit = random.sample(list(dimension.keys()), 2) scale = sympy.Rational(dimension[base_unit]) / dimension[target_unit] scale_non_decimal = _factor_non_decimal(sympy.denom(scale)) entropy = 9 if is_extrapolation else 7 base_value = number.non_integer_decimal(entropy, signed=False) base_value = display.Decimal(base_value.value * scale_non_decimal) target_value = display.Decimal(base_value.value * scale) return base_value, base_unit, target_value, target_unit
def integer_or_decimal(entropy, signed): """Returns integer or non-integer decimal; 50% probability of each.""" if random.choice([False, True]): # Represent it as a decimal so that arithmetic operations are supported: return display.Decimal(integer(entropy, signed)) else: return non_integer_decimal(entropy, signed)
def testRound(self): decimal = display.Decimal(sympy.Rational(2675, 1000)) # 2.675 self.assertEqual(sympy.sympify(decimal.round()), sympy.Integer(3)) self.assertEqual(sympy.sympify(decimal.round(1)), sympy.Rational(27, 10)) self.assertEqual(sympy.sympify(decimal.round(2)), sympy.Rational(268, 100)) self.assertEqual(sympy.sympify(decimal.round(3)), sympy.Rational(2675, 1000))
def testStr(self): self.assertEqual(str(display.Decimal(sympy.Rational(0, 10))), '0') self.assertEqual(str(display.Decimal(sympy.Rational(-1, 10))), '-0.1') self.assertEqual(str(display.Decimal(sympy.Rational(-11, 10))), '-1.1') self.assertEqual(str(display.Decimal(sympy.Rational(11, 10))), '1.1') self.assertEqual(str(display.Decimal(sympy.Rational(101, 1))), '101') self.assertEqual(str(display.Decimal(sympy.Rational(20171, 1000000))), '0.020171')
def testComparison(self): decimal = display.Decimal(sympy.Rational(-1, 2)) # pylint: disable=g-generic-assert self.assertFalse(decimal != -0.5) self.assertTrue(decimal != 0) self.assertFalse(decimal < -0.5) self.assertTrue(decimal < 0) self.assertTrue(decimal <= -0.5) self.assertTrue(decimal <= 0) self.assertFalse(decimal > -0.5) self.assertTrue(decimal > -1) self.assertTrue(decimal >= -0.5) self.assertFalse(decimal >= 0) self.assertFalse(decimal == 0) self.assertTrue(decimal == -0.5)
def non_integer_decimal(entropy, signed): """Returns a random decimal; integer divided by random power of ten. Guaranteed to be non-integer (i.e., numbers after the decimal point). Args: entropy: Float. signed: Boolean. Whether to also return negative numbers. Returns: Non-integer decimal. """ while True: base = integer(entropy, signed) shift = random.randint(1, int(math.ceil(entropy))) divisor = 10**shift if base % divisor != 0: return display.Decimal(sympy.Rational(base, divisor))
def testInt_errorIfNonInt(self): decimal = display.Decimal(sympy.Rational(1, 2)) with self.assertRaisesRegexp(TypeError, 'Cannot represent'): int(decimal)
def testInt(self): decimal = display.Decimal(123) self.assertEqual(int(decimal), 123)
def testMul(self): self.assertEqual((display.Decimal(2) * display.Decimal(3)).value, 6)
def testSub(self): self.assertEqual((display.Decimal(2) - display.Decimal(3)).value, -1)
def testAdd(self): self.assertEqual((display.Decimal(2) + display.Decimal(3)).value, 5)
def testStr_verySmall(self): # Tests it doesn't display in "scientific" notation 1E-9. decimal = display.Decimal(sympy.Rational(1, 1000000000)) self.assertEqual(str(decimal), '0.000000001')
def testBasic(self): decimal = display.Decimal(sympy.Rational(123, 100)) self.assertEqual(str(decimal), '1.23') self.assertEqual(sympy.sympify(decimal), sympy.Rational(123, 100)) self.assertEqual(decimal.decimal_places(), 2)
def testBasic_ten(self): decimal = display.Decimal(10) self.assertEqual(str(decimal), '10') self.assertEqual(sympy.sympify(decimal), sympy.Integer(10)) self.assertEqual(decimal.decimal_places(), 0)
def round_number(value, sample_args, context=None): """Question for rounding integers and decimals.""" del value # unused for now if context is None: context = composition.Context() entropy, sample_args = sample_args.peel() # This is the power of 10 to round to. E.g., power == 0 corresponds to # rounding to the nearest integer; power == -2 corresponds to rounding to two # decimal places, and power == 3 corresponds to rounding to the nearest 1000. power = random.randint(-7, 6) answer_entropy = 1 + random.uniform(0, entropy / 2) entropy = max(1, entropy - answer_entropy) value_integer = number.integer(answer_entropy, signed=True) remainder_divisor = 10**int(math.ceil(entropy)) remainder_range_lower = -remainder_divisor / 2 remainder_range_upper = remainder_divisor / 2 if value_integer <= 0: remainder_range_lower += 1 if value_integer >= 0: remainder_range_upper -= 1 remainder = random.randint(remainder_range_lower, remainder_range_upper) input_ = value_integer + sympy.Rational(remainder, remainder_divisor) scale = 10**power if power >= 0 else sympy.Rational(1, 10**(-power)) input_ = input_ * scale value = value_integer * scale if not number.is_integer(input_): input_ = display.Decimal(input_) if not number.is_integer(value): value = display.Decimal(value) (input_, ) = context.sample(sample_args, [input_]) des = False if power > 0: # Rounding to a power of ten. round_to = 10**power if round_to in [100, 1000]: if random.choice([False, True]): # Write the rounding value as a word instead. if round_to == 10: des = True round_to = display.StringNumber( round_to, case='do', desyatok=des, join_number_words_with_hyphens=False, singular=True) description = 'ближайшей {round_to}'.format(round_to=round_to) elif round_to in [1000000, 1000000000]: if random.choice([False, True]): # Write the rounding value as a word instead. if round_to == 10: des = True round_to = display.StringNumber( round_to, case='do', desyatok=des, join_number_words_with_hyphens=False, singular=True) description = 'ближайшего {round_to}'.format(round_to=round_to) else: if random.choice([False, True]): # Write the rounding value as a word instead. if round_to == 10: des = True round_to = display.StringNumber( round_to, case='do', desyatok=des, join_number_words_with_hyphens=False) description = 'ближайших {round_to}'.format(round_to=round_to) elif power == 0 and random.choice([False, True]): # Round to nearest integer. description = 'ближайшего целого числа' else: # Round to decimal places. description = '{dps} знак{ending} после запятой' # if power == 1: # # Plural # description += 's' dps = -power ending = ['а', 'ов', "ов"][check_one_ending(dps)] if random.choice([False, True]): dps = display.StringNumber(dps, case='do') description = description.format(dps=dps, ending=ending) template = random.choice([ 'Округлите {input} до {description}.', 'Сколько получится, если {input} округлить до {description}?', ]) return example.Problem(question=example.question(context, template, input=input_, description=description), answer=value)