当前位置: 首页 > 知识库问答 >
问题:

如何在PostgreSQL中精确地保留前两位小数来截断双精度值?

董鸣
2023-03-14

当我使用PostgreSQL 11.8中的json\u build\u object()函数构建json时,我试图截断双精度值,但运气不好。更准确地说,我试图将19.98999999999984数字截断为两位小数,但要确保它不会四舍五入到20.00(它就是这样做的),而是保持在19.98。

顺便说一句,我到目前为止尝试的是使用:
1)TRUNC(found_book.price::数字,2),我得到值20.00
2)ROound(found_book.price::数字,2)我得到值19.99-

[42883]错误:函数舍入(双精度,整数)不存在

下面是我使用的全部代码:

create or replace function public.get_book_by_book_id8(b_id bigint) returns json as
$BODY$
declare
    found_book book;
    book_authors json;
    book_categories json;
    book_price double precision;
begin
    -- Load book data:
    select * into found_book
    from book b2
    where b2.book_id  = b_id;

    -- Get assigned authors
    select case when count(x) = 0 then '[]' else json_agg(x) end into book_authors
    from (select aut.*
        from book b
        inner join author_book as ab on b.book_id = ab.book_id
        inner join author as aut on ab.author_id = aut.author_id
        where b.book_id = b_id) x;

    -- Get assigned categories
    select case when count(y) = 0 then '[]' else json_agg(y) end into book_categories
    from (select cat.*
        from book b
        inner join category_book as cb on b.book_id = cb.book_id
        inner join category as cat on cb.category_id = cat.category_id
        where b.book_id = b_id) y;

    book_price = trunc(found_book.price, 2);
    -- Build the JSON response:
    return (select json_build_object(
        'book_id', found_book.book_id,
        'title', found_book.title,
        'price', book_price,
        'amount', found_book.amount,
        'is_deleted', found_book.is_deleted,
        'authors', book_authors,
        'categories', book_categories
    ));
end
$BODY$
language 'plpgsql';

select get_book_by_book_id8(186);

我如何做到只保留前两位十进制数字19.98(非常感谢任何建议/帮助)?

PostgreSQL版本是11.8

共有2个答案

巫马正卿
2023-03-14

正如@pifor建议的那样,我已经通过直接将trunc(found\u book.price::double precision::text::numeric,2)作为json\u build\u对象中的值传递完成了它,如下所示:

json_build_object(
        'book_id', found_book.book_id,
        'title', found_book.title,
        'price', trunc(found_book.price::double precision::text::numeric, 2),
        'amount', found_book.amount,
        'is_deleted', found_book.is_deleted,
        'authors', book_authors,
        'categories', book_categories
    )

使用book_price=trunc(found_book.price::double精度::文本::数字,2);并将其作为价格键的值传递不起作用。

谢谢你的帮助。:)

谈琦
2023-03-14

在PostgreSQL 11.8或12.3我不能复制:

# select trunc('19.9899999999999984'::numeric, 2);
 trunc 
-------
 19.98
(1 row)

# select trunc(19.9899999999999984::numeric, 2);
 trunc 
-------
 19.98
(1 row)

# select trunc(19.9899999999999984, 2);
 trunc 
-------
 19.98
(1 row)

事实上,我可以用正确的类型和特殊的设置来复制:

# set extra_float_digits=0;
SET
# select trunc(19.9899999999999984::double precision::text::numeric, 2);
 trunc 
-------
 19.99
(1 row)

还有一个可能的解决方案

# show extra_float_digits;
 extra_float_digits 
--------------------
 3
(1 row)

select  trunc(19.9899999999999984::double precision::text::numeric, 2);
 trunc 
-------
 19.98
(1 row)

但请注意:

注意:额外浮点数设置控制浮点值转换为文本输出时包含的额外有效位数。默认值为0时,PostgreSQL支持的每个平台上的输出都相同。增加它将产生更准确地表示存储值的输出,但可能不可移植。

 类似资料:
  • 问题内容: 例如,我有变量3.545555555,我希望将其截断为3.54。 问题答案: 如果您希望将其用于显示目的,请使用: 如果需要进行计算,请使用:

  • 问题内容: 应该很容易。我本来是用javascript来做的,但是在设置我的处理程序页面中的表单之前必须先做。无论如何,我需要使这些值具有2个小数位。Ex 219333.5888888必须为219333.58。有修剪功能或其他功能吗? 问题答案: 这是格式化十进制值的简单示例

  • 问题内容: 我想使用双精度最多2个小数位。即,它将最多存储2个小数位,如果比较两个双精度值,则比较应仅基于前2个小数位。如何实现这样的事情?我的意思是存储,比较所有内容都将仅基于小数点后两位。其余位置可能不同,大于,小于,无所谓。 编辑 我的价值观不大。说从0到5000最大值。但是我必须乘以Cos A,Sin A很多次,其中A的值在程序过程中不断变化。 编辑 在我的程序中,汽车以特定速度(例如12

  • 问题内容: 我试图确定双精度的最大精度是多少。在此链接的可接受答案的注释中,Java中的double保持精度 @PeterLawrey将max precision设置为15。 您如何确定呢? 问题答案: @PeterLawrey表示最大精度为15。 实际上,这根本不是他所说的。他说的是: 双精度有15个小数位 他错了。它们的精度为15个十进制 数字 。 任何数字中的小数位数由其对数10的对数给出。

  • 我试图确定double的最大精度是多少。在这个链接中接受的答案的注释中,Java中的Retain precision with double@PeterLawrey声明max precision In 15。 你如何确定这一点?

  • 我想用一个小数点和一个小数位的格式将任何双精度四舍五入为双精度,这样29575.347434将是2.3。 我试着用decimalFormat做这个,但当我试着我只得到了一个29575.3格式的字符串,带有一个,我不知道如何在保留值为双精度的同时去掉所有小数点。