单位转换精度问题

时间:2016-11-15 19:09:50

标签: sql angularjs sql-server math asp.net-web-api2

寻求以下问题的解决方案。

在我们的应用程序中,我们具有根据用户选择转换单位的功能。例如根据用户的单位选择,将kg转换为lbs,反之亦然。

  1. 我们有一个屏幕,用户可以在其中选择提供价值的单位,例如Kg或lbs
  2. 我们有一个表格,其中包含我们系统支持的预定义单位的所有公式,例如 1Kg = 2.20462lbs ,如此
  3. 我们从数据库中获取公式,并使用用户提供的实际值计算/评估公式。
  4. 因为,用户可以根据自己的选择查看任何单位。我们决定仅在我们的数据库中以标准单位保存用户在屏幕上提供的值,以便于维护。在这种情况下,假设我们已经决定以kg为单位保存数据库但是,用户可能在屏幕上选择了“lbs”,但在保存时我们将'lbs'转换为'kg'然后我们将保存到数据库
  5. 从数据库读取时,如果用户打算在屏幕上看到'lbs',我们会转换为'lbs'
  6. 希望到现在为止实现清楚,现在上面解决的问题是

    1. 假设用户已选择值“1”作为“lbs”并保存
    2. 在数据库中,我们将保存为“kg”,因此“1”的值在数据库中保存为 2.20462
    3. 在再次阅读时,我们将转换为以'lbs'显示,现在我们得到的值为 0.999998 。由于公式
    4. 的精确性,这是预期的
    5. 但是用户要求至少显示他输入的相同值,在这种情况下为'1'但我们必须进行计算以将其转换回'lbs',因为我们在数据库中保存'kg'
    6. 我正在寻找这个问题的解决方案,这可能是最好的解决方案,而且变化很小。

      表定义

      Id | UnitConversion
      1  |   100
      2  |   200
      3  |   30 
      

      我们的应用程序是开发的 Angularjs,webapi和sql server

2 个答案:

答案 0 :(得分:1)

只是为了好玩,这是我的转换实用程序的精简版本。只是在这里展示MASS。通过将转换因子存储为varchar,精度处于单个记录级别。

Declare @Map table (MapType varchar(50),MapName varchar(50),MapValue varchar(50))
Insert Into @Map values
('Mass','tonnes (metric)','1000'),
('Mass','tons (US)'      ,'907.18474'),
('Mass','tons (UK)'      ,'1016.0469088'),
('Mass','stones'         ,'6.35029318'),
('Mass','slugs(g-pounds)','14.593903'),
('Mass','Solar masses'   ,'1.989e30'),
('Mass','pounds (troy)'  ,'0.3732417216'),
('Mass','pounds'         ,'0.45359237'),
('Mass','picograms'      ,'1e-15'),
('Mass','ounces'         ,'0.028349523'),
('Mass','ounces (troy)'  ,'0.0311034768'),
('Mass','nanograms'      ,'1e-12'),
('Mass','milligrams'     ,'1e-6'),
('Mass','micrograms'     ,'1e-9'),
('Mass','megatonnes'     ,'1e9'),
('Mass','kilotonnes'     ,'1e6'),
('Mass','kilograms'      ,'1'),               --- << Base
('Mass','hundredweights' ,'50.80234544'),
('Mass','hectograms'     ,'0.1'),
('Mass','grams'          ,'1e-3'),
('Mass','grains'         ,'0.00006479891'),
('Mass','femtograms'     ,'1e-18'),
('Mass','Earth masses'   ,'5.980e24'),
('Mass','decagrams'      ,'0.01'),
('Mass','cental'         ,'45.359237'),
('Mass','carats (metric)','0.0002')

Declare @Value float      = 1
Declare @From  varchar(50)= 'kilograms'
Declare @To    varchar(50)= 'pounds'

Select @Value * Max(IIF(MapName=@From,cast(MapValue as float),null))  / Max(IIF(MapName=@To,cast(MapValue as float),null)) 
 From  @Map 
 Where MapName in(@From,@To)

返回

2.20462262184878

答案 1 :(得分:0)

在Sql server端选择更精细的比例然后您需要返回到客户端。例如,如果您需要小数点右侧的5位数,请将DB列的比例设置为7

declare @n decimal(20,5) = 2.20462;

declare @t table (
      m decimal(20,7)
);

insert @t(m) values 
   (1./@n), 
  (10./@n), 
 (1000./@n);

select cast(m*@n as decimal(20,5)) as r 
from @t;

注意&#34;十进制和数字是同义词,可以互换使用。&#34; msdn.microsoft.com/en-us/library/ms187746.aspx