简体   繁体   English

科学记数法舍入行为

[英]Scientific notation rounding behaviour

Be it the numbers 'a', 'b', and 'c':无论是数字 'a'、'b' 和 '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)试图解决CodeWars 的 Kata ,我需要计算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 .然而,它足以阻止我通过,因为它被解释为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.由于@GreenCloakGuy 的评论解决了我的问题(如所示),我决定添加实际代码(和测试),因为给定的解决方案对我不起作用。 I'm using Python 3.8.6我正在使用 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)正确使用整数除法(感谢@GreenCloakGuy 和@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.如果lcm使用浮点除法,十进制也会起作用,但我想无论如何我都会进行修复,因为它是有道理的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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