简体   繁体   中英

Scientific notation rounding behaviour

Be it the numbers 'a', 'b', and 'c':

a = 77033412951888085
b = a - 5
c = 2840988860479

A division produces the following result

>>> a/c, b/c
(27115.0, 27115.0)

Attempting to solve a CodeWars' Kata , I'm required to calculate a = 14949283383840498 * 27115 / 5262)

However, instead of getting

77033412951888085

I get

7.703341295188808e+16

... which is... only but slightly wrong , sigh. Yet it's wrong enough to prevent me from passing, as it's interpreted as 77033412951888080 . And...

>>> 14949283383840498 * 27115 / 5262 == 77033412951888085
False

EDIT:

As @GreenCloakGuy 's comment solves my issue (as presented), I've decided to add actual code (and tests), since the given solution does not work for me. I'm using Python 3.8.6

import functools

def gcd(a:int, b:int) -> int:
    'Recursive function to return gcd of a and b'
    if a == 0:
        return b
    return gcd(b % a, a)

def lcm(a:int, b:int) -> int:
    'Function to return LCM of two numbers'
    return a / gcd(a, b) * b

def convertFracts(fractions:list) -> list:
    if len(fractions) == 0:
        return []
    denominators = [i[1] for i in fractions]
    LCM = functools.reduce(lambda a, b: lcm(a, b), denominators)
    # Here I attempt so use @GreenCloakGuy 's solution, and use floor division.
    return [[num * LCM // den, LCM] for num, den in fractions]

import unittest
class TestSolution(unittest.TestCase):
    #@unittest.skip
    def test_sample(self):
        a = [[1, 2], [1, 3], [1, 4]]
        b = [[6, 12], [4, 12], [3, 12]]
        self.assertEqual(convertFracts(a), b)

    @staticmethod
    def simplifyFractions(result: list):
        for numerator, denominator in result:
            GCD = gcd(numerator, denominator)
            yield [numerator/GCD, denominator/GCD]

    @unittest.expectedFailure
    def test_failed(self):
        #Test result I got problems with
        test_result = [[77033412951888085, 14949283383840498],
                       [117787497858828, 14949283383840498],
                       [2526695441399712, 14949283383840498]
                       ]

        #Infer initial simplified fractions
        starting_fractions = [fraction for fraction in self.simplifyFractions(test_result)]
        print('Infered starting fractions: ', starting_fractions)

        my_result = convertFracts(starting_fractions)
        print('My result: ', my_result)
        my_result_as_int = list(map(lambda x: [int(x[0]), int(x[1])], convertFracts(my_result)))
        print('My result as int: ', my_result_as_int)
        self.assertEqual(test_result, my_result_as_int)

Two ways to make it work:

  1. Correct use of integer division (thanks to @GreenCloakGuy and @MarkDickinson)
  2. Using decimal.Decimal. Could be a duplicate of this question

Decimal has worked for me. Here's the updated code (only imports and updated function):

With correct use of //

import functools

#def gcd

def lcm(a:int, b:int) -> int:
    'Function to return LCM of two numbers'
    return a // gcd(a, b) * b

def convertFracts(fractions:list) -> list:
    if len(fractions) == 0:
        return []
    denominators = [i[1] for i in fractions]
    least_common_multiple = functools.reduce(lambda a, b: lcm(a, b), denominators)
    return [[num * least_common_multiple // den, least_common_multiple] for num, den in fractions]

With Decimal:

import functools
from decimal import Decimal

#def gcd

def lcm(a:int, b:int) -> int:
    'Function to return LCM of two numbers'
    return a // gcd(a, b) * b

def convertFracts(fractions:list) -> list:
    if len(fractions) == 0:
        return []
    denominators = [i[1] for i in fractions]
    least_common_multiple = Decimal(functools.reduce(lambda a, b: lcm(a, b), denominators))
    return [[Decimal(num) * least_common_multiple / Decimal(den), least_common_multiple] for num, den in fractions]

Decimal would have also worked if lcm used float division, but I figured I'd make the fix anyways, as it makes sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM