Chop or truncate to n significant digits
Asked Answered
P

3

5

Julia has a built-in function to round to n significant digits. signif(0.0229, 2) will round to two significant digits and give 0.023.

How can I chop or truncate to n significant digits so that I would get 0.022 instead?

Parts answered 18/9, 2017 at 22:35 Comment(3)
Will myfloor(x,d) = round(x-0.5*10.0^(-d),d) be good enough?Vizza
myfloor(0.0229, 2) yields 0.02, it should yield 0.022Parts
Ah... I see, misunderstood the question. But have a lengthy but working suggestion in an answer below.Vizza
F
3

Note that signif was removed as of Julia 1.0.

However, now Base.round accepts the sigdigits keyword:

julia> round(pi, digits=3)
3.142

julia> round(pi, sigdigits=3)
3.14

The same works for trunc, ceil, and floor.

Source: mforets on Github and @DNF in the comments.


Fredricfredrick answered 26/1, 2023 at 3:13 Comment(3)
And the same works with trunc, ceil and floor.Reynaldoreynard
I think it would be useful, actually, if you expand this answer a bit, include trunc/ceil/floor and also mention that the signif function was removed in v1.0. This would be the updated correct answer for v1.Reynaldoreynard
This is a better answer for recent versions of Julia. trunc(0.0229, sigdigits=2) is a much simpler answer. The original question was over six years ago well before 1.0 existed.Parts
V
3

Well, not very imaginative. Used @edit signif(0.229,2) to find the source and replace round with floor (and added a Base. for correct Module referencing). Here is the result:

function mysignif(x::Real, digits::Integer, base::Integer=10)
    digits < 1 && throw(DomainError(digits, "`digits` cannot be less than 1."))

    x = float(x)
    (x == 0 || !isfinite(x)) && return x
    og, e = Base._signif_og(x, digits, base)
    if e >= 0 # for numeric stability
        r = trunc(x/og)*og
    else
        r = trunc(x*og)/og
    end
    !isfinite(r) ? x : r
end

Giving:

julia> mysignif(0.0229,2)
0.022
Vizza answered 18/9, 2017 at 23:16 Comment(2)
Impressive. It doesn't handle negative numbers correctly. I'm sure that you can easily fix that.Parts
@Parts Yes it is easily fixed (in fact, the desired behavior on negatives depends on the application). To fix, replace floor with trunc [I'll do it in the answer, as well]Vizza
F
3

Note that signif was removed as of Julia 1.0.

However, now Base.round accepts the sigdigits keyword:

julia> round(pi, digits=3)
3.142

julia> round(pi, sigdigits=3)
3.14

The same works for trunc, ceil, and floor.

Source: mforets on Github and @DNF in the comments.


Fredricfredrick answered 26/1, 2023 at 3:13 Comment(3)
And the same works with trunc, ceil and floor.Reynaldoreynard
I think it would be useful, actually, if you expand this answer a bit, include trunc/ceil/floor and also mention that the signif function was removed in v1.0. This would be the updated correct answer for v1.Reynaldoreynard
This is a better answer for recent versions of Julia. trunc(0.0229, sigdigits=2) is a much simpler answer. The original question was over six years ago well before 1.0 existed.Parts
P
2

I found a version in Maple and ported to Julia:

function signifChop(num, digits)
    if num == 0.0 then
        return num
    else
        e = ceil(log10(abs(num)))
        scale = 10^(digits - e)
        return trunc(num * scale) / scale
    end
end

# Test cases for signifChop
println("$(signifChop(124.031, 5))")
println("$(signifChop(124.036, 5))")
println("$(signifChop(-124.031, 5))")
println("$(signifChop(-124.036, 5))")
println("$(signifChop(0.00653, 2))")
println("$(signifChop(0.00656, 2))")
println("$(signifChop(-0.00653, 2))")
println("$(signifChop(-0.00656, 2))")
Parts answered 19/9, 2017 at 4:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.