Amazon DynamoDB の UpdateItem の Add 構文による数値計算で、小数点以下の誤差が出ないのか確認してみた

検証では小数点16位程度で出るようになりました。
2023.09.20

こんにちは、CX事業本部 Delivery部の若槻です。

Amazon DynamoDB でテーブル上のアイテムの数値属性を UpdateItem を使用して更新する際に、Add 構文を使用して加減計算を行うことができます。

次のような記述で、更新前の値を取得することなく値の足し算または引き算が可能なので、ロックを考慮する必要がありません。

aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD QuantityOnHand :q" \
    --expression-attribute-values '{":q": {"N": "5"}}' \
    --return-values ALL_NEW

さてこのとても便利な Add 構文ですが、計算される側またはする側の値が少数の時に、浮動小数点による計算誤差は出ないのでしょうか?気になったので検証してみました。

試してみた

テーブル作成

AWS CDK で検証用のテーブルを作成します。

lib/cdk-sample-stack.ts

import { aws_dynamodb, Stack, CfnOutput } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class CdkSampleStack extends Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const table = new aws_dynamodb.Table(this, 'Table', {
      partitionKey: { name: 'id', type: aws_dynamodb.AttributeType.STRING },
      billingMode: aws_dynamodb.BillingMode.PAY_PER_REQUEST,
    });

    new CfnOutput(this, 'TableName', {
      value: table.tableName,
    });
  }
}

検証用スクリプト

0.01 から 1 までの値を設定した 100 個の属性を持つアイテムを PutItem で作成し、それら属性に対して同じ値を加算(減算)する UpdateItem を実行するスクリプトです。AWS SDK for JavaScript v3 を使用しています。

script.ts

import { marshall, unmarshall } from '@aws-sdk/util-dynamodb';
import {
  PutItemCommand,
  PutItemCommandInput,
  UpdateItemCommand,
  UpdateItemCommandInput,
  DynamoDBClient,
  ReturnValue,
} from '@aws-sdk/client-dynamodb';

const ADDITION = Number(process.argv[2]) || 0.01;
const TABLE_NAME = process.env.TABLE_NAME || '';

const client = new DynamoDBClient({
  region: 'ap-northeast-1',
});

const numValues = Array.from(Array(100), (_, i) => (i + 1) / 100);
const numValueAttrs = numValues.map(
  (numValue) => `numValue${numValue.toString().replace('.', '')}`
);

export const main = async (addition: number): Promise<void> => {
  // PutItem: numValue001: 0.01 から numValue1: 1.00 までの値を設定
  const putObject = numValues.reduce((acc, numValue) => {
    return {
      ...acc,
      [`numValue${numValue.toString().replace('.', '')}`]: numValue,
    };
  }, {});
  const putParams: PutItemCommandInput = {
    TableName: TABLE_NAME,
    Item: marshall({
      id: 'test',
      ...putObject,
    }),
  };
  await client.send(new PutItemCommand(putParams));

  // UpdateItem: numValue001 から numValue1 までの属性値を、指定値ずつ加算
  const expressionAttributeNames = numValueAttrs.reduce(
    (acc, numValueAttr) => ({
      ...acc,
      [`#${numValueAttr}`]: numValueAttr,
    }),
    {}
  );
  const updateExpression = `SET ${numValueAttrs
    .map((numValueAttr) => `#${numValueAttr} = #${numValueAttr} + :numValue`)
    .join(', ')}`;
  const updateParams: UpdateItemCommandInput = {
    TableName: TABLE_NAME,
    Key: marshall({
      id: 'test',
    }),
    UpdateExpression: updateExpression,
    ExpressionAttributeNames: expressionAttributeNames,
    ExpressionAttributeValues: marshall({
      ':numValue': addition,
    }),
    ReturnValues: ReturnValue.ALL_NEW,
  };
  const updateResult = await client.send(new UpdateItemCommand(updateParams));
  const updatedItem = unmarshall(updateResult.Attributes!);
  const updateObject = Object.keys(updatedItem)
    .sort()
    .reduce((acc, key) => {
      return {
        ...acc,
        [key]: updatedItem[key],
      };
    }, {});

  // putObject と updateObject の比較をテーブル形式で出力
  const keys = Object.keys(putObject);
  const values = keys.map((key) => ({
    key,
    putValue: (putObject as any)[key],
    updateValue: (updateObject as any)[key],
  }));
  const table = values.reduce((acc, value) => {
    return `${acc}${value.key}\t${value.putValue}\t${value.updateValue}\n`;
  }, '');
  console.log(table);
};

main(ADDITION);

検証

その1

各属性に 0.01 を加算した場合。

$ npx ts-node script.ts
numValue001     0.01    0.02
numValue002     0.02    0.03
numValue003     0.03    0.04
numValue004     0.04    0.05
numValue005     0.05    0.06
numValue006     0.06    0.07
numValue007     0.07    0.08
numValue008     0.08    0.09
numValue009     0.09    0.1
numValue01      0.1     0.11
numValue011     0.11    0.12
numValue012     0.12    0.13
numValue013     0.13    0.14
numValue014     0.14    0.15
numValue015     0.15    0.16
numValue016     0.16    0.17
numValue017     0.17    0.18
numValue018     0.18    0.19
numValue019     0.19    0.2
numValue02      0.2     0.21
numValue021     0.21    0.22
numValue022     0.22    0.23
numValue023     0.23    0.24
numValue024     0.24    0.25
numValue025     0.25    0.26
numValue026     0.26    0.27
numValue027     0.27    0.28
numValue028     0.28    0.29
numValue029     0.29    0.3
numValue03      0.3     0.31
numValue031     0.31    0.32
numValue032     0.32    0.33
numValue033     0.33    0.34
numValue034     0.34    0.35
numValue035     0.35    0.36
numValue036     0.36    0.37
numValue037     0.37    0.38
numValue038     0.38    0.39
numValue039     0.39    0.4
numValue04      0.4     0.41
numValue041     0.41    0.42
numValue042     0.42    0.43
numValue043     0.43    0.44
numValue044     0.44    0.45
numValue045     0.45    0.46
numValue046     0.46    0.47
numValue047     0.47    0.48
numValue048     0.48    0.49
numValue049     0.49    0.5
numValue05      0.5     0.51
numValue051     0.51    0.52
numValue052     0.52    0.53
numValue053     0.53    0.54
numValue054     0.54    0.55
numValue055     0.55    0.56
numValue056     0.56    0.57
numValue057     0.57    0.58
numValue058     0.58    0.59
numValue059     0.59    0.6
numValue06      0.6     0.61
numValue061     0.61    0.62
numValue062     0.62    0.63
numValue063     0.63    0.64
numValue064     0.64    0.65
numValue065     0.65    0.66
numValue066     0.66    0.67
numValue067     0.67    0.68
numValue068     0.68    0.69
numValue069     0.69    0.7
numValue07      0.7     0.71
numValue071     0.71    0.72
numValue072     0.72    0.73
numValue073     0.73    0.74
numValue074     0.74    0.75
numValue075     0.75    0.76
numValue076     0.76    0.77
numValue077     0.77    0.78
numValue078     0.78    0.79
numValue079     0.79    0.8
numValue08      0.8     0.81
numValue081     0.81    0.82
numValue082     0.82    0.83
numValue083     0.83    0.84
numValue084     0.84    0.85
numValue085     0.85    0.86
numValue086     0.86    0.87
numValue087     0.87    0.88
numValue088     0.88    0.89
numValue089     0.89    0.9
numValue09      0.9     0.91
numValue091     0.91    0.92
numValue092     0.92    0.93
numValue093     0.93    0.94
numValue094     0.94    0.95
numValue095     0.95    0.96
numValue096     0.96    0.97
numValue097     0.97    0.98
numValue098     0.98    0.99
numValue099     0.99    1
numValue1       1       1.01

大丈夫そうです。

その2

各属性に 0.1 を加算した場合。

$ npx ts-node script.ts 0.1                     
numValue001     0.01    0.11
numValue002     0.02    0.12
numValue003     0.03    0.13
numValue004     0.04    0.14
numValue005     0.05    0.15
numValue006     0.06    0.16
numValue007     0.07    0.17
numValue008     0.08    0.18
numValue009     0.09    0.19
numValue01      0.1     0.2
numValue011     0.11    0.21
numValue012     0.12    0.22
numValue013     0.13    0.23
numValue014     0.14    0.24
numValue015     0.15    0.25
numValue016     0.16    0.26
numValue017     0.17    0.27
numValue018     0.18    0.28
numValue019     0.19    0.29
numValue02      0.2     0.3
numValue021     0.21    0.31
numValue022     0.22    0.32
numValue023     0.23    0.33
numValue024     0.24    0.34
numValue025     0.25    0.35
numValue026     0.26    0.36
numValue027     0.27    0.37
numValue028     0.28    0.38
numValue029     0.29    0.39
numValue03      0.3     0.4
numValue031     0.31    0.41
numValue032     0.32    0.42
numValue033     0.33    0.43
numValue034     0.34    0.44
numValue035     0.35    0.45
numValue036     0.36    0.46
numValue037     0.37    0.47
numValue038     0.38    0.48
numValue039     0.39    0.49
numValue04      0.4     0.5
numValue041     0.41    0.51
numValue042     0.42    0.52
numValue043     0.43    0.53
numValue044     0.44    0.54
numValue045     0.45    0.55
numValue046     0.46    0.56
numValue047     0.47    0.57
numValue048     0.48    0.58
numValue049     0.49    0.59
numValue05      0.5     0.6
numValue051     0.51    0.61
numValue052     0.52    0.62
numValue053     0.53    0.63
numValue054     0.54    0.64
numValue055     0.55    0.65
numValue056     0.56    0.66
numValue057     0.57    0.67
numValue058     0.58    0.68
numValue059     0.59    0.69
numValue06      0.6     0.7
numValue061     0.61    0.71
numValue062     0.62    0.72
numValue063     0.63    0.73
numValue064     0.64    0.74
numValue065     0.65    0.75
numValue066     0.66    0.76
numValue067     0.67    0.77
numValue068     0.68    0.78
numValue069     0.69    0.79
numValue07      0.7     0.8
numValue071     0.71    0.81
numValue072     0.72    0.82
numValue073     0.73    0.83
numValue074     0.74    0.84
numValue075     0.75    0.85
numValue076     0.76    0.86
numValue077     0.77    0.87
numValue078     0.78    0.88
numValue079     0.79    0.89
numValue08      0.8     0.9
numValue081     0.81    0.91
numValue082     0.82    0.92
numValue083     0.83    0.93
numValue084     0.84    0.94
numValue085     0.85    0.95
numValue086     0.86    0.96
numValue087     0.87    0.97
numValue088     0.88    0.98
numValue089     0.89    0.99
numValue09      0.9     1
numValue091     0.91    1.01
numValue092     0.92    1.02
numValue093     0.93    1.03
numValue094     0.94    1.04
numValue095     0.95    1.05
numValue096     0.96    1.06
numValue097     0.97    1.07
numValue098     0.98    1.08
numValue099     0.99    1.09
numValue1       1       1.1

大丈夫そうです。

その3

各属性に 0.001 を加算した場合。

$ npx ts-node script.ts 0.001
numValue001     0.01    0.011
numValue002     0.02    0.021
numValue003     0.03    0.031
numValue004     0.04    0.041
numValue005     0.05    0.051
numValue006     0.06    0.061
numValue007     0.07    0.071
numValue008     0.08    0.081
numValue009     0.09    0.091
numValue01      0.1     0.101
numValue011     0.11    0.111
numValue012     0.12    0.121
numValue013     0.13    0.131
numValue014     0.14    0.141
numValue015     0.15    0.151
numValue016     0.16    0.161
numValue017     0.17    0.171
numValue018     0.18    0.181
numValue019     0.19    0.191
numValue02      0.2     0.201
numValue021     0.21    0.211
numValue022     0.22    0.221
numValue023     0.23    0.231
numValue024     0.24    0.241
numValue025     0.25    0.251
numValue026     0.26    0.261
numValue027     0.27    0.271
numValue028     0.28    0.281
numValue029     0.29    0.291
numValue03      0.3     0.301
numValue031     0.31    0.311
numValue032     0.32    0.321
numValue033     0.33    0.331
numValue034     0.34    0.341
numValue035     0.35    0.351
numValue036     0.36    0.361
numValue037     0.37    0.371
numValue038     0.38    0.381
numValue039     0.39    0.391
numValue04      0.4     0.401
numValue041     0.41    0.411
numValue042     0.42    0.421
numValue043     0.43    0.431
numValue044     0.44    0.441
numValue045     0.45    0.451
numValue046     0.46    0.461
numValue047     0.47    0.471
numValue048     0.48    0.481
numValue049     0.49    0.491
numValue05      0.5     0.501
numValue051     0.51    0.511
numValue052     0.52    0.521
numValue053     0.53    0.531
numValue054     0.54    0.541
numValue055     0.55    0.551
numValue056     0.56    0.561
numValue057     0.57    0.571
numValue058     0.58    0.581
numValue059     0.59    0.591
numValue06      0.6     0.601
numValue061     0.61    0.611
numValue062     0.62    0.621
numValue063     0.63    0.631
numValue064     0.64    0.641
numValue065     0.65    0.651
numValue066     0.66    0.661
numValue067     0.67    0.671
numValue068     0.68    0.681
numValue069     0.69    0.691
numValue07      0.7     0.701
numValue071     0.71    0.711
numValue072     0.72    0.721
numValue073     0.73    0.731
numValue074     0.74    0.741
numValue075     0.75    0.751
numValue076     0.76    0.761
numValue077     0.77    0.771
numValue078     0.78    0.781
numValue079     0.79    0.791
numValue08      0.8     0.801
numValue081     0.81    0.811
numValue082     0.82    0.821
numValue083     0.83    0.831
numValue084     0.84    0.841
numValue085     0.85    0.851
numValue086     0.86    0.861
numValue087     0.87    0.871
numValue088     0.88    0.881
numValue089     0.89    0.891
numValue09      0.9     0.901
numValue091     0.91    0.911
numValue092     0.92    0.921
numValue093     0.93    0.931
numValue094     0.94    0.941
numValue095     0.95    0.951
numValue096     0.96    0.961
numValue097     0.97    0.971
numValue098     0.98    0.981
numValue099     0.99    0.991
numValue1       1       1.001

大丈夫そうです。

その4

各属性から 0.01 を減算した場合。

$ npx ts-node src/script.ts -0.01
numValue001     0.01    0
numValue002     0.02    0.01
numValue003     0.03    0.02
numValue004     0.04    0.03
numValue005     0.05    0.04
numValue006     0.06    0.05
numValue007     0.07    0.06
numValue008     0.08    0.07
numValue009     0.09    0.08
numValue01      0.1     0.09
numValue011     0.11    0.1
numValue012     0.12    0.11
numValue013     0.13    0.12
numValue014     0.14    0.13
numValue015     0.15    0.14
numValue016     0.16    0.15
numValue017     0.17    0.16
numValue018     0.18    0.17
numValue019     0.19    0.18
numValue02      0.2     0.19
numValue021     0.21    0.2
numValue022     0.22    0.21
numValue023     0.23    0.22
numValue024     0.24    0.23
numValue025     0.25    0.24
numValue026     0.26    0.25
numValue027     0.27    0.26
numValue028     0.28    0.27
numValue029     0.29    0.28
numValue03      0.3     0.29
numValue031     0.31    0.3
numValue032     0.32    0.31
numValue033     0.33    0.32
numValue034     0.34    0.33
numValue035     0.35    0.34
numValue036     0.36    0.35
numValue037     0.37    0.36
numValue038     0.38    0.37
numValue039     0.39    0.38
numValue04      0.4     0.39
numValue041     0.41    0.4
numValue042     0.42    0.41
numValue043     0.43    0.42
numValue044     0.44    0.43
numValue045     0.45    0.44
numValue046     0.46    0.45
numValue047     0.47    0.46
numValue048     0.48    0.47
numValue049     0.49    0.48
numValue05      0.5     0.49
numValue051     0.51    0.5
numValue052     0.52    0.51
numValue053     0.53    0.52
numValue054     0.54    0.53
numValue055     0.55    0.54
numValue056     0.56    0.55
numValue057     0.57    0.56
numValue058     0.58    0.57
numValue059     0.59    0.58
numValue06      0.6     0.59
numValue061     0.61    0.6
numValue062     0.62    0.61
numValue063     0.63    0.62
numValue064     0.64    0.63
numValue065     0.65    0.64
numValue066     0.66    0.65
numValue067     0.67    0.66
numValue068     0.68    0.67
numValue069     0.69    0.68
numValue07      0.7     0.69
numValue071     0.71    0.7
numValue072     0.72    0.71
numValue073     0.73    0.72
numValue074     0.74    0.73
numValue075     0.75    0.74
numValue076     0.76    0.75
numValue077     0.77    0.76
numValue078     0.78    0.77
numValue079     0.79    0.78
numValue08      0.8     0.79
numValue081     0.81    0.8
numValue082     0.82    0.81
numValue083     0.83    0.82
numValue084     0.84    0.83
numValue085     0.85    0.84
numValue086     0.86    0.85
numValue087     0.87    0.86
numValue088     0.88    0.87
numValue089     0.89    0.88
numValue09      0.9     0.89
numValue091     0.91    0.9
numValue092     0.92    0.91
numValue093     0.93    0.92
numValue094     0.94    0.93
numValue095     0.95    0.94
numValue096     0.96    0.95
numValue097     0.97    0.96
numValue098     0.98    0.97
numValue099     0.99    0.98
numValue1       1       0.99

大丈夫そうです。

その5

各属性に 0.000000000000001 を加算した場合。

$ npx ts-node src/script.ts 0.000000000000001
numValue001     0.01    0.010000000000001
numValue002     0.02    0.020000000000001
numValue003     0.03    0.030000000000001
numValue004     0.04    0.040000000000001
numValue005     0.05    0.050000000000001
numValue006     0.06    0.060000000000001
numValue007     0.07    0.070000000000001
numValue008     0.08    0.080000000000001
numValue009     0.09    0.090000000000001
numValue01      0.1     0.100000000000001
numValue011     0.11    0.110000000000001
numValue012     0.12    0.120000000000001
numValue013     0.13    0.130000000000001
numValue014     0.14    0.140000000000001
numValue015     0.15    0.150000000000001
numValue016     0.16    0.160000000000001
numValue017     0.17    0.170000000000001
numValue018     0.18    0.180000000000001
numValue019     0.19    0.190000000000001
numValue02      0.2     0.200000000000001
numValue021     0.21    0.210000000000001
numValue022     0.22    0.220000000000001
numValue023     0.23    0.230000000000001
numValue024     0.24    0.240000000000001
numValue025     0.25    0.250000000000001
numValue026     0.26    0.260000000000001
numValue027     0.27    0.270000000000001
numValue028     0.28    0.280000000000001
numValue029     0.29    0.290000000000001
numValue03      0.3     0.300000000000001
numValue031     0.31    0.310000000000001
numValue032     0.32    0.320000000000001
numValue033     0.33    0.330000000000001
numValue034     0.34    0.340000000000001
numValue035     0.35    0.350000000000001
numValue036     0.36    0.360000000000001
numValue037     0.37    0.370000000000001
numValue038     0.38    0.380000000000001
numValue039     0.39    0.390000000000001
numValue04      0.4     0.400000000000001
numValue041     0.41    0.410000000000001
numValue042     0.42    0.420000000000001
numValue043     0.43    0.430000000000001
numValue044     0.44    0.440000000000001
numValue045     0.45    0.450000000000001
numValue046     0.46    0.460000000000001
numValue047     0.47    0.470000000000001
numValue048     0.48    0.480000000000001
numValue049     0.49    0.490000000000001
numValue05      0.5     0.500000000000001
numValue051     0.51    0.510000000000001
numValue052     0.52    0.520000000000001
numValue053     0.53    0.530000000000001
numValue054     0.54    0.540000000000001
numValue055     0.55    0.550000000000001
numValue056     0.56    0.560000000000001
numValue057     0.57    0.570000000000001
numValue058     0.58    0.580000000000001
numValue059     0.59    0.590000000000001
numValue06      0.6     0.600000000000001
numValue061     0.61    0.610000000000001
numValue062     0.62    0.620000000000001
numValue063     0.63    0.630000000000001
numValue064     0.64    0.640000000000001
numValue065     0.65    0.650000000000001
numValue066     0.66    0.660000000000001
numValue067     0.67    0.670000000000001
numValue068     0.68    0.680000000000001
numValue069     0.69    0.690000000000001
numValue07      0.7     0.700000000000001
numValue071     0.71    0.710000000000001
numValue072     0.72    0.720000000000001
numValue073     0.73    0.730000000000001
numValue074     0.74    0.740000000000001
numValue075     0.75    0.750000000000001
numValue076     0.76    0.760000000000001
numValue077     0.77    0.770000000000001
numValue078     0.78    0.780000000000001
numValue079     0.79    0.790000000000001
numValue08      0.8     0.800000000000001
numValue081     0.81    0.810000000000001
numValue082     0.82    0.820000000000001
numValue083     0.83    0.830000000000001
numValue084     0.84    0.840000000000001
numValue085     0.85    0.850000000000001
numValue086     0.86    0.860000000000001
numValue087     0.87    0.870000000000001
numValue088     0.88    0.880000000000001
numValue089     0.89    0.890000000000001
numValue09      0.9     0.900000000000001
numValue091     0.91    0.910000000000001
numValue092     0.92    0.920000000000001
numValue093     0.93    0.930000000000001
numValue094     0.94    0.940000000000001
numValue095     0.95    0.950000000000001
numValue096     0.96    0.960000000000001
numValue097     0.97    0.970000000000001
numValue098     0.98    0.980000000000001
numValue099     0.99    0.990000000000001
numValue1       1       1.000000000000001

大丈夫そうです。

その6

各属性に 0.0000000000000001 を加算した場合。

$ npx ts-node src/script.ts 0.0000000000000001 
numValue001     0.01    0.0100000000000001
numValue002     0.02    0.0200000000000001
numValue003     0.03    0.0300000000000001
numValue004     0.04    0.0400000000000001
numValue005     0.05    0.0500000000000001
numValue006     0.06    0.0600000000000001
numValue007     0.07    0.0700000000000001
numValue008     0.08    0.0800000000000001
numValue009     0.09    0.0900000000000001
numValue01      0.1     0.1000000000000001
numValue011     0.11    0.1100000000000001
numValue012     0.12    0.1200000000000001
numValue013     0.13    0.1300000000000001
numValue014     0.14    0.1400000000000001
numValue015     0.15    0.1500000000000001
numValue016     0.16    0.1600000000000001
numValue017     0.17    0.1700000000000001
numValue018     0.18    0.1800000000000001
numValue019     0.19    0.1900000000000001
numValue02      0.2     0.2000000000000001
numValue021     0.21    0.2100000000000001
numValue022     0.22    0.2200000000000001
numValue023     0.23    0.2300000000000001
numValue024     0.24    0.2400000000000001
numValue025     0.25    0.2500000000000001
numValue026     0.26    0.2600000000000001
numValue027     0.27    0.2700000000000001
numValue028     0.28    0.2800000000000001
numValue029     0.29    0.2900000000000001
numValue03      0.3     0.3000000000000001
numValue031     0.31    0.3100000000000001
numValue032     0.32    0.3200000000000001
numValue033     0.33    0.3300000000000001
numValue034     0.34    0.3400000000000001
numValue035     0.35    0.3500000000000001
numValue036     0.36    0.3600000000000001
numValue037     0.37    0.3700000000000001
numValue038     0.38    0.3800000000000001
numValue039     0.39    0.3900000000000001
numValue04      0.4     0.4000000000000001
numValue041     0.41    0.4100000000000001
numValue042     0.42    0.4200000000000001
numValue043     0.43    0.4300000000000001
numValue044     0.44    0.4400000000000001
numValue045     0.45    0.4500000000000001
numValue046     0.46    0.4600000000000001
numValue047     0.47    0.4700000000000001
numValue048     0.48    0.4800000000000001
numValue049     0.49    0.4900000000000001
numValue05      0.5     0.5000000000000001
numValue051     0.51    0.5100000000000001
numValue052     0.52    0.5200000000000001
numValue053     0.53    0.5300000000000001
numValue054     0.54    0.5400000000000001
numValue055     0.55    0.5500000000000002
numValue056     0.56    0.56
numValue057     0.57    0.5700000000000001
numValue058     0.58    0.5800000000000001
numValue059     0.59    0.5900000000000001
numValue06      0.6     0.6000000000000001
numValue061     0.61    0.6100000000000001
numValue062     0.62    0.6200000000000001
numValue063     0.63    0.6300000000000001
numValue064     0.64    0.6400000000000001
numValue065     0.65    0.6500000000000001
numValue066     0.66    0.6600000000000001
numValue067     0.67    0.6700000000000002
numValue068     0.68    0.68
numValue069     0.69    0.6900000000000001
numValue07      0.7     0.7000000000000001
numValue071     0.71    0.7100000000000001
numValue072     0.72    0.7200000000000001
numValue073     0.73    0.7300000000000001
numValue074     0.74    0.7400000000000001
numValue075     0.75    0.7500000000000001
numValue076     0.76    0.7600000000000001
numValue077     0.77    0.7700000000000001
numValue078     0.78    0.7800000000000001
numValue079     0.79    0.7900000000000001
numValue08      0.8     0.8000000000000002
numValue081     0.81    0.81
numValue082     0.82    0.8200000000000001
numValue083     0.83    0.8300000000000001
numValue084     0.84    0.8400000000000001
numValue085     0.85    0.8500000000000001
numValue086     0.86    0.8600000000000001
numValue087     0.87    0.8700000000000001
numValue088     0.88    0.8800000000000001
numValue089     0.89    0.8900000000000001
numValue09      0.9     0.9000000000000001
numValue091     0.91    0.9100000000000001
numValue092     0.92    0.9200000000000002
numValue093     0.93    0.93
numValue094     0.94    0.9400000000000001
numValue095     0.95    0.9500000000000001
numValue096     0.96    0.9600000000000001
numValue097     0.97    0.9700000000000001
numValue098     0.98    0.9800000000000001
numValue099     0.99    0.9900000000000001
numValue1       1       1

ここに来て誤差が発生しました。一部の属性で加算した少数が扱われなくなっています。

その7

各属性に 0.00000000000000001 を加算した場合。

$ npx ts-node src/script.ts 0.00000000000000001
numValue001     0.01    0.01000000000000001
numValue002     0.02    0.02000000000000001
numValue003     0.03    0.03000000000000001
numValue004     0.04    0.04000000000000001
numValue005     0.05    0.05000000000000001
numValue006     0.06    0.06000000000000001
numValue007     0.07    0.07
numValue008     0.08    0.08000000000000002
numValue009     0.09    0.09000000000000001
numValue01      0.1     0.1
numValue011     0.11    0.11000000000000001
numValue012     0.12    0.12000000000000001
numValue013     0.13    0.13
numValue014     0.14    0.14
numValue015     0.15    0.15000000000000002
numValue016     0.16    0.16
numValue017     0.17    0.17
numValue018     0.18    0.18000000000000002
numValue019     0.19    0.19
numValue02      0.2     0.2
numValue021     0.21    0.21000000000000002
numValue022     0.22    0.22
numValue023     0.23    0.23
numValue024     0.24    0.24000000000000002
numValue025     0.25    0.25
numValue026     0.26    0.26
numValue027     0.27    0.27
numValue028     0.28    0.28
numValue029     0.29    0.29000000000000004
numValue03      0.3     0.3
numValue031     0.31    0.31
numValue032     0.32    0.32
numValue033     0.33    0.33
numValue034     0.34    0.34
numValue035     0.35    0.35000000000000003
numValue036     0.36    0.36
numValue037     0.37    0.37
numValue038     0.38    0.38
numValue039     0.39    0.39
numValue04      0.4     0.4
numValue041     0.41    0.41000000000000003
numValue042     0.42    0.42
numValue043     0.43    0.43
numValue044     0.44    0.44
numValue045     0.45    0.45
numValue046     0.46    0.46
numValue047     0.47    0.47000000000000003
numValue048     0.48    0.48000000000000004
numValue049     0.49    0.49
numValue05      0.5     0.5
numValue051     0.51    0.51
numValue052     0.52    0.52
numValue053     0.53    0.53
numValue054     0.54    0.54
numValue055     0.55    0.55
numValue056     0.56    0.56
numValue057     0.57    0.5700000000000001
numValue058     0.58    0.58
numValue059     0.59    0.59
numValue06      0.6     0.6
numValue061     0.61    0.61
numValue062     0.62    0.62
numValue063     0.63    0.63
numValue064     0.64    0.64
numValue065     0.65    0.65
numValue066     0.66    0.66
numValue067     0.67    0.67
numValue068     0.68    0.68
numValue069     0.69    0.6900000000000001
numValue07      0.7     0.7
numValue071     0.71    0.71
numValue072     0.72    0.72
numValue073     0.73    0.73
numValue074     0.74    0.74
numValue075     0.75    0.75
numValue076     0.76    0.76
numValue077     0.77    0.77
numValue078     0.78    0.78
numValue079     0.79    0.79
numValue08      0.8     0.8
numValue081     0.81    0.81
numValue082     0.82    0.8200000000000001
numValue083     0.83    0.83
numValue084     0.84    0.84
numValue085     0.85    0.85
numValue086     0.86    0.86
numValue087     0.87    0.87
numValue088     0.88    0.88
numValue089     0.89    0.89
numValue09      0.9     0.9
numValue091     0.91    0.91
numValue092     0.92    0.92
numValue093     0.93    0.93
numValue094     0.94    0.9400000000000001
numValue095     0.95    0.95
numValue096     0.96    0.96
numValue097     0.97    0.97
numValue098     0.98    0.98
numValue099     0.99    0.99
numValue1       1       1

誤差が発生しました。一部の属性で加算した少数が扱われなくなっています。

その8

各属性に 0.000000000000000001 を加算した場合。

$ npx ts-node src/script.ts 0.000000000000000001
numValue001     0.01    0.01
numValue002     0.02    0.02
numValue003     0.03    0.030000000000000002
numValue004     0.04    0.04
numValue005     0.05    0.05
numValue006     0.06    0.06
numValue007     0.07    0.07
numValue008     0.08    0.08
numValue009     0.09    0.09
numValue01      0.1     0.1
numValue011     0.11    0.11
numValue012     0.12    0.12
numValue013     0.13    0.13
numValue014     0.14    0.14
numValue015     0.15    0.15
numValue016     0.16    0.16
numValue017     0.17    0.17
numValue018     0.18    0.18
numValue019     0.19    0.19
numValue02      0.2     0.2
numValue021     0.21    0.21
numValue022     0.22    0.22
numValue023     0.23    0.23
numValue024     0.24    0.24
numValue025     0.25    0.25
numValue026     0.26    0.26
numValue027     0.27    0.27
numValue028     0.28    0.28
numValue029     0.29    0.29
numValue03      0.3     0.3
numValue031     0.31    0.31
numValue032     0.32    0.32
numValue033     0.33    0.33
numValue034     0.34    0.34
numValue035     0.35    0.35
numValue036     0.36    0.36
numValue037     0.37    0.37
numValue038     0.38    0.38
numValue039     0.39    0.39
numValue04      0.4     0.4
numValue041     0.41    0.41
numValue042     0.42    0.42
numValue043     0.43    0.43
numValue044     0.44    0.44
numValue045     0.45    0.45
numValue046     0.46    0.46
numValue047     0.47    0.47
numValue048     0.48    0.48
numValue049     0.49    0.49
numValue05      0.5     0.5
numValue051     0.51    0.51
numValue052     0.52    0.52
numValue053     0.53    0.53
numValue054     0.54    0.54
numValue055     0.55    0.55
numValue056     0.56    0.56
numValue057     0.57    0.57
numValue058     0.58    0.58
numValue059     0.59    0.59
numValue06      0.6     0.6
numValue061     0.61    0.61
numValue062     0.62    0.62
numValue063     0.63    0.63
numValue064     0.64    0.64
numValue065     0.65    0.65
numValue066     0.66    0.66
numValue067     0.67    0.67
numValue068     0.68    0.68
numValue069     0.69    0.69
numValue07      0.7     0.7
numValue071     0.71    0.71
numValue072     0.72    0.72
numValue073     0.73    0.73
numValue074     0.74    0.74
numValue075     0.75    0.75
numValue076     0.76    0.76
numValue077     0.77    0.77
numValue078     0.78    0.78
numValue079     0.79    0.79
numValue08      0.8     0.8
numValue081     0.81    0.81
numValue082     0.82    0.82
numValue083     0.83    0.83
numValue084     0.84    0.84
numValue085     0.85    0.85
numValue086     0.86    0.86
numValue087     0.87    0.87
numValue088     0.88    0.88
numValue089     0.89    0.89
numValue09      0.9     0.9
numValue091     0.91    0.91
numValue092     0.92    0.92
numValue093     0.93    0.93
numValue094     0.94    0.94
numValue095     0.95    0.95
numValue096     0.96    0.96
numValue097     0.97    0.97
numValue098     0.98    0.98
numValue099     0.99    0.99
numValue1       1       1

誤差が発生しました。一部(というよりほぼすべて)の属性で加算した少数が扱われなくなっています。

その9

各属性に 0.0000000000000000001 を加算した場合。

$ npx ts-node src/script.ts 0.0000000000000000001
numValue001     0.01    0.01
numValue002     0.02    0.02
numValue003     0.03    0.03
numValue004     0.04    0.04
numValue005     0.05    0.05
numValue006     0.06    0.06
numValue007     0.07    0.07
numValue008     0.08    0.08
numValue009     0.09    0.09
numValue01      0.1     0.1
numValue011     0.11    0.11
numValue012     0.12    0.12
numValue013     0.13    0.13
numValue014     0.14    0.14
numValue015     0.15    0.15
numValue016     0.16    0.16
numValue017     0.17    0.17
numValue018     0.18    0.18
numValue019     0.19    0.19
numValue02      0.2     0.2
numValue021     0.21    0.21
numValue022     0.22    0.22
numValue023     0.23    0.23
numValue024     0.24    0.24
numValue025     0.25    0.25
numValue026     0.26    0.26
numValue027     0.27    0.27
numValue028     0.28    0.28
numValue029     0.29    0.29
numValue03      0.3     0.3
numValue031     0.31    0.31
numValue032     0.32    0.32
numValue033     0.33    0.33
numValue034     0.34    0.34
numValue035     0.35    0.35
numValue036     0.36    0.36
numValue037     0.37    0.37
numValue038     0.38    0.38
numValue039     0.39    0.39
numValue04      0.4     0.4
numValue041     0.41    0.41
numValue042     0.42    0.42
numValue043     0.43    0.43
numValue044     0.44    0.44
numValue045     0.45    0.45
numValue046     0.46    0.46
numValue047     0.47    0.47
numValue048     0.48    0.48
numValue049     0.49    0.49
numValue05      0.5     0.5
numValue051     0.51    0.51
numValue052     0.52    0.52
numValue053     0.53    0.53
numValue054     0.54    0.54
numValue055     0.55    0.55
numValue056     0.56    0.56
numValue057     0.57    0.57
numValue058     0.58    0.58
numValue059     0.59    0.59
numValue06      0.6     0.6
numValue061     0.61    0.61
numValue062     0.62    0.62
numValue063     0.63    0.63
numValue064     0.64    0.64
numValue065     0.65    0.65
numValue066     0.66    0.66
numValue067     0.67    0.67
numValue068     0.68    0.68
numValue069     0.69    0.69
numValue07      0.7     0.7
numValue071     0.71    0.71
numValue072     0.72    0.72
numValue073     0.73    0.73
numValue074     0.74    0.74
numValue075     0.75    0.75
numValue076     0.76    0.76
numValue077     0.77    0.77
numValue078     0.78    0.78
numValue079     0.79    0.79
numValue08      0.8     0.8
numValue081     0.81    0.81
numValue082     0.82    0.82
numValue083     0.83    0.83
numValue084     0.84    0.84
numValue085     0.85    0.85
numValue086     0.86    0.86
numValue087     0.87    0.87
numValue088     0.88    0.88
numValue089     0.89    0.89
numValue09      0.9     0.9
numValue091     0.91    0.91
numValue092     0.92    0.92
numValue093     0.93    0.93
numValue094     0.94    0.94
numValue095     0.95    0.95
numValue096     0.96    0.96
numValue097     0.97    0.97
numValue098     0.98    0.98
numValue099     0.99    0.99
numValue1       1       1

誤差が発生しました。すべての属性で加算した少数が扱われなくなっています。

おわりに

Amazon DynamoDB の UpdateItem の Add 構文による数値計算で、小数点以下の誤差が出ないのか確認してみました。

小数点16位くらいから誤差が発生するようになりました。少数を含む数値属性の加減に Add 構文を使わない方が良さそうです。回避策としては、以下のようなものが考えられます。

  • Add 構文を使わない:一度アイテムを取得した上で、計算および楽観的ロック(※)を伴う更新を行う(こちらが参考になります)
  • Add 構文を使う:少数の最大位が分かっている場合は、保管時に整数に変換する

どなかたの参考になれば幸いです。

以上