TypeError:Decimal与float类型不支持/运算的问题求助
Hey there! I see you've been stuck on this error all day—let's break it down and fix it step by step.
What's causing the error?
The error pops up in your normalized() method when you try to divide a Decimal by a float:
return self.times_scalar(Decimal('1.0')/magnitude)
Your magnitude() method uses math.sqrt(), which returns a float value. Python doesn't allow direct division between Decimal and float types—they're incompatible for arithmetic operations like this.
How to fix it
We need to make sure all calculations involving Decimal values stay within the Decimal type system. Here are the key changes:
Update the
magnitude()method to return a Decimal
Replacemath.sqrt()with theDecimal.sqrt()method so the result is a Decimal instead of a float:def magnitude(self): coordinates_squared = [x**2 for x in self.coordinates] return Decimal(sum(coordinates_squared)).sqrt()Fix type mismatches in comparison checks
Methods likeis_zero()andis_orthogonal_to()compare Decimal values against float tolerances. Convert the tolerance to Decimal to avoid type warnings:def is_zero(self, tolerance=1e-10): return self.magnitude() < Decimal(tolerance) def is_orthogonal_to(self, v, tolerance=1e-10): return abs(self.dot(v)) < Decimal(tolerance)Adjust
angle_with()for Decimal compatibility
Themath.acos()function can't accept Decimal inputs directly. Convert the dot product result to a float before passing it toacos:def angle_with(self,v,in_degrees=False): try: u1 = self.normalized() u2 = v.normalized() dot_product = u1.dot(u2) # Convert Decimal to float for math.acos angle_in_radians = acos(float(dot_product)) if in_degrees: degrees_per_radian = Decimal('180') / Decimal(str(pi)) return float(angle_in_radians * degrees_per_radian) else: return angle_in_radians except Exception as e: if str(e) == self.CANNOT_NORMALIZE_ZERO_VECTOR_MSG: raise Exception('Cannot compute an angle with the zero vector') else: raise e
Full corrected code
from math import sqrt, acos, pi from decimal import Decimal, getcontext getcontext().prec = 30 class Vector(object): CANNOT_NORMALIZE_ZERO_VECTOR_MSG = 'Cannot compute an angle with the zero vector' def __init__(self, coordinates): try: if not coordinates: raise ValueError self.coordinates = tuple(Decimal(x) for x in coordinates) self.dimension = len(self.coordinates) except ValueError: raise ValueError('The coordinates must be nonempty') except TypeError: raise TypeError('The coordinates must be an iterable') #orthogonal or parallel def is_zero(self, tolerance=1e-10): return self.magnitude() < Decimal(tolerance) def is_orthogonal_to(self, v, tolerance=1e-10): return abs(self.dot(v)) < Decimal(tolerance) def is_parallel_to(self, v): return ( self.is_zero() or v.is_zero() or self.angle_with(v) == 0 or self.angle_with(v) == pi ) #dot product &angle def dot(self, v): return sum([x*y for x,y in zip(self.coordinates,v.coordinates)]) def angle_with(self,v,in_degrees=False): try: u1 = self.normalized() u2 = v.normalized() dot_product = u1.dot(u2) angle_in_radians = acos(float(dot_product)) if in_degrees: degrees_per_radian = Decimal('180') / Decimal(str(pi)) return float(angle_in_radians * degrees_per_radian) else: return angle_in_radians except Exception as e: if str(e) == self.CANNOT_NORMALIZE_ZERO_VECTOR_MSG: raise Exception('Cannot compute an angle with the zero vector') else: raise e #magnitude& Direction def magnitude(self): coordinates_squared = [x**2 for x in self.coordinates] return Decimal(sum(coordinates_squared)).sqrt() def normalized(self): try: magnitude = self.magnitude() return self.times_scalar(Decimal('1.0') / magnitude) except ZeroDivisionError: raise Exception(self.CANNOT_NORMALIZE_ZERO_VECTOR_MSG) #Plus,minus, scalar multiply def plus(self, v): new_coordinates = [x+y for x,y in zip(self.coordinates,v.coordinates)] return Vector(new_coordinates) def minus(self, v): new_coordinates = [x-y for x,y in zip(self.coordinates,v.coordinates)] return Vector(new_coordinates) def times_scalar(self, c): new_coordinates = [Decimal(c)*x for x in self.coordinates] return Vector(new_coordinates) def __str__(self): return 'Vector: {}'.format(self.coordinates) def __eq__(self, v): return self.coordinates == v.coordinates v = Vector(['8','-9']) w = Vector(['-1','-1']) print(v.dot(w)) print(v.angle_with(w)) print(v.angle_with(w, in_degrees=True))
Why this works
By keeping all core vector calculations within the Decimal type, we eliminate the cross-type arithmetic error. The only conversion to float happens when we need to use math.acos(), which is safe here because the dot product of normalized vectors will always be between -1 and 1, and converting to float won't lose meaningful precision for angle calculations.
内容的提问来源于stack exchange,提问作者kathy

